Fix for LayoutTests/accessibility/mac/search-text/search-text.html in IsolatedTree...
[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     auto* backingObject = self.updateObjectBackingStore;
1338     if (!backingObject)
1339         return nil;
1340
1341     return textMarkerRangeFromVisiblePositions(backingObject->axObjectCache(), startPosition, endPosition);
1342 }
1343
1344 ALLOW_DEPRECATED_IMPLEMENTATIONS_BEGIN
1345 - (NSArray*)accessibilityActionNames
1346 ALLOW_DEPRECATED_IMPLEMENTATIONS_END
1347 {
1348     auto* backingObject = self.updateObjectBackingStore;
1349     if (!backingObject)
1350         return nil;
1351
1352     // All elements should get ShowMenu and ScrollToVisible.
1353     // But certain earlier VoiceOver versions do not support scroll to visible, and it confuses them to see it in the list.
1354     static NSArray *defaultElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityShowMenuAction, NSAccessibilityScrollToVisibleAction, nil];
1355
1356     // Action elements allow Press.
1357     // 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.
1358     static NSArray *actionElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityPressAction, NSAccessibilityShowMenuAction, NSAccessibilityScrollToVisibleAction, nil];
1359
1360     // Menu elements allow Press and Cancel.
1361     static NSArray *menuElementActions = [[actionElementActions arrayByAddingObject:NSAccessibilityCancelAction] retain];
1362
1363     // Slider elements allow Increment/Decrement.
1364     static NSArray *sliderActions = [[defaultElementActions arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:NSAccessibilityIncrementAction, NSAccessibilityDecrementAction, nil]] retain];
1365
1366     NSArray *actions;
1367     if (backingObject->supportsPressAction())
1368         actions = actionElementActions;
1369     else if (backingObject->isMenuRelated())
1370         actions = menuElementActions;
1371     else if (backingObject->isSlider())
1372         actions = sliderActions;
1373     else if (backingObject->isAttachment())
1374         actions = [[self attachmentView] accessibilityActionNames];
1375     else
1376         actions = defaultElementActions;
1377
1378     return actions;
1379 }
1380
1381 - (NSArray*)additionalAccessibilityAttributeNames
1382 {
1383     auto* backingObject = self.axBackingObject;
1384     if (!backingObject)
1385         return nil;
1386
1387     NSMutableArray *additional = [NSMutableArray array];
1388     if (backingObject->supportsARIAOwns())
1389         [additional addObject:NSAccessibilityOwnsAttribute];
1390
1391     if (backingObject->isToggleButton())
1392         [additional addObject:NSAccessibilityValueAttribute];
1393
1394     if (backingObject->supportsExpanded() || backingObject->isSummary())
1395         [additional addObject:NSAccessibilityExpandedAttribute];
1396
1397     if (backingObject->isScrollbar()
1398         || backingObject->isRadioGroup()
1399         || backingObject->isSplitter()
1400         || backingObject->isToolbar())
1401         [additional addObject:NSAccessibilityOrientationAttribute];
1402
1403     if (backingObject->supportsARIADragging())
1404         [additional addObject:NSAccessibilityGrabbedAttribute];
1405
1406     if (backingObject->supportsARIADropping())
1407         [additional addObject:NSAccessibilityDropEffectsAttribute];
1408
1409     if (backingObject->isTable() && backingObject->isExposable() && backingObject->supportsSelectedRows())
1410         [additional addObject:NSAccessibilitySelectedRowsAttribute];
1411
1412     if (backingObject->supportsLiveRegion()) {
1413         [additional addObject:NSAccessibilityARIALiveAttribute];
1414         [additional addObject:NSAccessibilityARIARelevantAttribute];
1415     }
1416
1417     if (backingObject->supportsSetSize())
1418         [additional addObject:NSAccessibilityARIASetSizeAttribute];
1419
1420     if (backingObject->supportsPosInSet())
1421         [additional addObject:NSAccessibilityARIAPosInSetAttribute];
1422
1423     AccessibilitySortDirection sortDirection = backingObject->sortDirection();
1424     if (sortDirection != AccessibilitySortDirection::None && sortDirection != AccessibilitySortDirection::Invalid)
1425         [additional addObject:NSAccessibilitySortDirectionAttribute];
1426
1427     // If an object is a child of a live region, then add these
1428     if (backingObject->isInsideLiveRegion())
1429         [additional addObject:NSAccessibilityARIAAtomicAttribute];
1430
1431     // All objects should expose the ARIA busy attribute (ARIA 1.1 with ISSUE-538).
1432     [additional addObject:NSAccessibilityElementBusyAttribute];
1433
1434     // Popup buttons on the Mac expose the value attribute.
1435     if (backingObject->isPopUpButton())
1436         [additional addObject:NSAccessibilityValueAttribute];
1437
1438     if (backingObject->supportsDatetimeAttribute())
1439         [additional addObject:NSAccessibilityDatetimeValueAttribute];
1440
1441     if (backingObject->supportsRequiredAttribute())
1442         [additional addObject:NSAccessibilityRequiredAttribute];
1443
1444     if (backingObject->hasPopup())
1445         [additional addObject:NSAccessibilityHasPopupAttribute];
1446
1447     if (backingObject->isMathRoot()) {
1448         // The index of a square root is always known, so there's no object associated with it.
1449         if (!backingObject->isMathSquareRoot())
1450             [additional addObject:NSAccessibilityMathRootIndexAttribute];
1451         [additional addObject:NSAccessibilityMathRootRadicandAttribute];
1452     } else if (backingObject->isMathFraction()) {
1453         [additional addObject:NSAccessibilityMathFractionNumeratorAttribute];
1454         [additional addObject:NSAccessibilityMathFractionDenominatorAttribute];
1455         [additional addObject:NSAccessibilityMathLineThicknessAttribute];
1456     } else if (backingObject->isMathSubscriptSuperscript()) {
1457         [additional addObject:NSAccessibilityMathBaseAttribute];
1458         [additional addObject:NSAccessibilityMathSubscriptAttribute];
1459         [additional addObject:NSAccessibilityMathSuperscriptAttribute];
1460     } else if (backingObject->isMathUnderOver()) {
1461         [additional addObject:NSAccessibilityMathBaseAttribute];
1462         [additional addObject:NSAccessibilityMathUnderAttribute];
1463         [additional addObject:NSAccessibilityMathOverAttribute];
1464     } else if (backingObject->isMathFenced()) {
1465         [additional addObject:NSAccessibilityMathFencedOpenAttribute];
1466         [additional addObject:NSAccessibilityMathFencedCloseAttribute];
1467     } else if (backingObject->isMathMultiscript()) {
1468         [additional addObject:NSAccessibilityMathBaseAttribute];
1469         [additional addObject:NSAccessibilityMathPrescriptsAttribute];
1470         [additional addObject:NSAccessibilityMathPostscriptsAttribute];
1471     }
1472
1473     if (backingObject->supportsPath())
1474         [additional addObject:NSAccessibilityPathAttribute];
1475
1476     if (backingObject->supportsExpandedTextValue())
1477         [additional addObject:NSAccessibilityExpandedTextValueAttribute];
1478
1479 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
1480     if (_AXUIElementRequestServicedBySecondaryAXThread() && AXObjectCache::clientSupportsIsolatedTree())
1481         [additional addObject:NSAccessibilityRelativeFrameAttribute];
1482 #endif
1483     
1484     return additional;
1485 }
1486
1487 ALLOW_DEPRECATED_IMPLEMENTATIONS_BEGIN
1488 - (NSArray*)accessibilityAttributeNames
1489 ALLOW_DEPRECATED_IMPLEMENTATIONS_END
1490 {
1491     auto* backingObject = self.axBackingObject;
1492     if (!backingObject)
1493         return nil;
1494
1495     if (backingObject->isAttachment())
1496         return [[self attachmentView] accessibilityAttributeNames];
1497
1498     static NSArray* attributes = nil;
1499     static NSArray* anchorAttrs = nil;
1500     static NSArray* webAreaAttrs = nil;
1501     static NSArray* textAttrs = nil;
1502     static NSArray* listAttrs = nil;
1503     static NSArray* listBoxAttrs = nil;
1504     static NSArray* rangeAttrs = nil;
1505     static NSArray* commonMenuAttrs = nil;
1506     static NSArray* menuAttrs = nil;
1507     static NSArray* menuBarAttrs = nil;
1508     static NSArray* menuItemAttrs = nil;
1509     static NSArray* menuButtonAttrs = nil;
1510     static NSArray* controlAttrs = nil;
1511     static NSArray* tableAttrs = nil;
1512     static NSArray* tableRowAttrs = nil;
1513     static NSArray* tableColAttrs = nil;
1514     static NSArray* tableCellAttrs = nil;
1515     static NSArray* groupAttrs = nil;
1516     static NSArray* inputImageAttrs = nil;
1517     static NSArray* passwordFieldAttrs = nil;
1518     static NSArray* tabListAttrs = nil;
1519     static NSArray* comboBoxAttrs = nil;
1520     static NSArray* outlineAttrs = nil;
1521     static NSArray* outlineRowAttrs = nil;
1522     static NSArray* buttonAttrs = nil;
1523     static NSArray* scrollViewAttrs = nil;
1524     static NSArray* incrementorAttrs = nil;
1525     NSMutableArray* tempArray;
1526     if (attributes == nil) {
1527         attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1528             NSAccessibilitySubroleAttribute,
1529             NSAccessibilityRoleDescriptionAttribute,
1530             NSAccessibilityChildrenAttribute,
1531             NSAccessibilityHelpAttribute,
1532             NSAccessibilityParentAttribute,
1533             NSAccessibilityPositionAttribute,
1534             NSAccessibilitySizeAttribute,
1535             NSAccessibilityTitleAttribute,
1536             NSAccessibilityDescriptionAttribute,
1537             NSAccessibilityValueAttribute,
1538             NSAccessibilityFocusedAttribute,
1539             NSAccessibilityEnabledAttribute,
1540             NSAccessibilityWindowAttribute,
1541             @"AXSelectedTextMarkerRange",
1542             @"AXStartTextMarker",
1543             @"AXEndTextMarker",
1544             @"AXVisited",
1545             NSAccessibilityLinkedUIElementsAttribute,
1546             NSAccessibilitySelectedAttribute,
1547             NSAccessibilityBlockQuoteLevelAttribute,
1548             NSAccessibilityTopLevelUIElementAttribute,
1549             NSAccessibilityLanguageAttribute,
1550             NSAccessibilityDOMIdentifierAttribute,
1551             NSAccessibilityDOMClassListAttribute,
1552             NSAccessibilityFocusableAncestorAttribute,
1553             NSAccessibilityEditableAncestorAttribute,
1554             NSAccessibilityHighestEditableAncestorAttribute,
1555             nil];
1556     }
1557     if (commonMenuAttrs == nil) {
1558         commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1559                            NSAccessibilityRoleDescriptionAttribute,
1560                            NSAccessibilityChildrenAttribute,
1561                            NSAccessibilityParentAttribute,
1562                            NSAccessibilityEnabledAttribute,
1563                            NSAccessibilityPositionAttribute,
1564                            NSAccessibilitySizeAttribute,
1565                            nil];
1566     }
1567     if (anchorAttrs == nil) {
1568         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1569         [tempArray addObject:NSAccessibilityURLAttribute];
1570         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1571         [tempArray addObject:NSAccessibilityLinkRelationshipTypeAttribute];
1572         anchorAttrs = [[NSArray alloc] initWithArray:tempArray];
1573         [tempArray release];
1574     }
1575     if (webAreaAttrs == nil) {
1576         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1577         // WebAreas should not expose AXSubrole.
1578         [tempArray removeObject:NSAccessibilitySubroleAttribute];
1579         // WebAreas should not expose ancestor attributes
1580         [tempArray removeObject:NSAccessibilityFocusableAncestorAttribute];
1581         [tempArray removeObject:NSAccessibilityEditableAncestorAttribute];
1582         [tempArray removeObject:NSAccessibilityHighestEditableAncestorAttribute];
1583         [tempArray addObject:@"AXLinkUIElements"];
1584         [tempArray addObject:@"AXLoaded"];
1585         [tempArray addObject:@"AXLayoutCount"];
1586         [tempArray addObject:NSAccessibilityLoadingProgressAttribute];
1587         [tempArray addObject:NSAccessibilityURLAttribute];
1588         [tempArray addObject:NSAccessibilityCaretBrowsingEnabledAttribute];
1589         [tempArray addObject:NSAccessibilityPreventKeyboardDOMEventDispatchAttribute];
1590         [tempArray addObject:NSAccessibilityWebSessionIDAttribute];
1591         webAreaAttrs = [[NSArray alloc] initWithArray:tempArray];
1592         [tempArray release];
1593     }
1594     if (textAttrs == nil) {
1595         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1596         [tempArray addObject:NSAccessibilityNumberOfCharactersAttribute];
1597         [tempArray addObject:NSAccessibilitySelectedTextAttribute];
1598         [tempArray addObject:NSAccessibilitySelectedTextRangeAttribute];
1599         [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute];
1600         [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute];
1601         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1602         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1603         [tempArray addObject:NSAccessibilityRequiredAttribute];
1604         [tempArray addObject:NSAccessibilityInvalidAttribute];
1605         [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1606         [tempArray addObject:NSAccessibilityValueAutofilledAttribute];
1607         textAttrs = [[NSArray alloc] initWithArray:tempArray];
1608         [tempArray release];
1609     }
1610     if (listAttrs == nil) {
1611         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1612         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1613         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1614         [tempArray addObject:NSAccessibilityOrientationAttribute];
1615         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1616         listAttrs = [[NSArray alloc] initWithArray:tempArray];
1617         [tempArray release];
1618     }
1619     if (listBoxAttrs == nil) {
1620         tempArray = [[NSMutableArray alloc] initWithArray:listAttrs];
1621         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1622         [tempArray addObject:NSAccessibilityRequiredAttribute];
1623         [tempArray addObject:NSAccessibilityInvalidAttribute];
1624         [tempArray addObject:NSAccessibilityOrientationAttribute];
1625         listBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1626         [tempArray release];
1627     }
1628     if (rangeAttrs == nil) {
1629         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1630         [tempArray addObject:NSAccessibilityMinValueAttribute];
1631         [tempArray addObject:NSAccessibilityMaxValueAttribute];
1632         [tempArray addObject:NSAccessibilityOrientationAttribute];
1633         [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1634         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1635         rangeAttrs = [[NSArray alloc] initWithArray:tempArray];
1636         [tempArray release];
1637     }
1638     if (menuBarAttrs == nil) {
1639         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1640         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1641         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1642         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1643         [tempArray addObject:NSAccessibilityOrientationAttribute];
1644         menuBarAttrs = [[NSArray alloc] initWithArray:tempArray];
1645         [tempArray release];
1646     }
1647     if (menuAttrs == nil) {
1648         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1649         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1650         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1651         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1652         [tempArray addObject:NSAccessibilityOrientationAttribute];
1653         menuAttrs = [[NSArray alloc] initWithArray:tempArray];
1654         [tempArray release];
1655     }
1656     if (menuItemAttrs == nil) {
1657         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1658         [tempArray addObject:NSAccessibilityTitleAttribute];
1659         [tempArray addObject:NSAccessibilityDescriptionAttribute];
1660         [tempArray addObject:NSAccessibilityHelpAttribute];
1661         [tempArray addObject:NSAccessibilitySelectedAttribute];
1662         [tempArray addObject:NSAccessibilityValueAttribute];
1663         [tempArray addObject:(NSString*)kAXMenuItemCmdCharAttribute];
1664         [tempArray addObject:(NSString*)kAXMenuItemCmdVirtualKeyAttribute];
1665         [tempArray addObject:(NSString*)kAXMenuItemCmdGlyphAttribute];
1666         [tempArray addObject:(NSString*)kAXMenuItemCmdModifiersAttribute];
1667         [tempArray addObject:(NSString*)kAXMenuItemMarkCharAttribute];
1668         [tempArray addObject:(NSString*)kAXMenuItemPrimaryUIElementAttribute];
1669         [tempArray addObject:NSAccessibilityServesAsTitleForUIElementsAttribute];
1670         [tempArray addObject:NSAccessibilityFocusedAttribute];
1671         menuItemAttrs = [[NSArray alloc] initWithArray:tempArray];
1672         [tempArray release];
1673     }
1674     if (menuButtonAttrs == nil) {
1675         menuButtonAttrs = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute,
1676                            NSAccessibilityRoleDescriptionAttribute,
1677                            NSAccessibilityParentAttribute,
1678                            NSAccessibilityPositionAttribute,
1679                            NSAccessibilitySizeAttribute,
1680                            NSAccessibilityWindowAttribute,
1681                            NSAccessibilityEnabledAttribute,
1682                            NSAccessibilityFocusedAttribute,
1683                            NSAccessibilityTitleAttribute,
1684                            NSAccessibilityChildrenAttribute, nil];
1685     }
1686     if (controlAttrs == nil) {
1687         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1688         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1689         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1690         [tempArray addObject:NSAccessibilityRequiredAttribute];
1691         [tempArray addObject:NSAccessibilityInvalidAttribute];
1692         controlAttrs = [[NSArray alloc] initWithArray:tempArray];
1693         [tempArray release];
1694     }
1695     if (incrementorAttrs == nil) {
1696         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1697         [tempArray addObject:NSAccessibilityIncrementButtonAttribute];
1698         [tempArray addObject:NSAccessibilityDecrementButtonAttribute];
1699         [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1700         [tempArray addObject:NSAccessibilityMinValueAttribute];
1701         [tempArray addObject:NSAccessibilityMaxValueAttribute];
1702         incrementorAttrs = [[NSArray alloc] initWithArray:tempArray];
1703         [tempArray release];
1704     }
1705     if (buttonAttrs == nil) {
1706         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1707         // Buttons should not expose AXValue.
1708         [tempArray removeObject:NSAccessibilityValueAttribute];
1709         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1710         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1711         buttonAttrs = [[NSArray alloc] initWithArray:tempArray];
1712         [tempArray release];
1713     }
1714     if (comboBoxAttrs == nil) {
1715         tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs];
1716         [tempArray addObject:NSAccessibilityExpandedAttribute];
1717         [tempArray addObject:NSAccessibilityOrientationAttribute];
1718         comboBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1719         [tempArray release];
1720     }
1721     if (tableAttrs == nil) {
1722         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1723         [tempArray addObject:NSAccessibilityRowsAttribute];
1724         [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1725         [tempArray addObject:NSAccessibilityColumnsAttribute];
1726         [tempArray addObject:NSAccessibilityVisibleColumnsAttribute];
1727         [tempArray addObject:NSAccessibilityVisibleCellsAttribute];
1728         [tempArray addObject:NSAccessibilityColumnHeaderUIElementsAttribute];
1729         [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1730         [tempArray addObject:NSAccessibilityHeaderAttribute];
1731         [tempArray addObject:NSAccessibilityColumnCountAttribute];
1732         [tempArray addObject:NSAccessibilityRowCountAttribute];
1733         [tempArray addObject:NSAccessibilityARIAColumnCountAttribute];
1734         [tempArray addObject:NSAccessibilityARIARowCountAttribute];
1735         tableAttrs = [[NSArray alloc] initWithArray:tempArray];
1736         [tempArray release];
1737     }
1738     if (tableRowAttrs == nil) {
1739         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1740         [tempArray addObject:NSAccessibilityIndexAttribute];
1741         tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1742         [tempArray release];
1743     }
1744     if (tableColAttrs == nil) {
1745         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1746         [tempArray addObject:NSAccessibilityIndexAttribute];
1747         [tempArray addObject:NSAccessibilityHeaderAttribute];
1748         [tempArray addObject:NSAccessibilityRowsAttribute];
1749         [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1750         tableColAttrs = [[NSArray alloc] initWithArray:tempArray];
1751         [tempArray release];
1752     }
1753     if (tableCellAttrs == nil) {
1754         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1755         [tempArray addObject:NSAccessibilityRowIndexRangeAttribute];
1756         [tempArray addObject:NSAccessibilityColumnIndexRangeAttribute];
1757         [tempArray addObject:NSAccessibilityColumnHeaderUIElementsAttribute];
1758         [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1759         [tempArray addObject:NSAccessibilityARIAColumnIndexAttribute];
1760         [tempArray addObject:NSAccessibilityARIARowIndexAttribute];
1761         tableCellAttrs = [[NSArray alloc] initWithArray:tempArray];
1762         [tempArray release];
1763     }
1764     if (groupAttrs == nil) {
1765         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1766         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1767         groupAttrs = [[NSArray alloc] initWithArray:tempArray];
1768         [tempArray release];
1769     }
1770     if (inputImageAttrs == nil) {
1771         tempArray = [[NSMutableArray alloc] initWithArray:buttonAttrs];
1772         [tempArray addObject:NSAccessibilityURLAttribute];
1773         inputImageAttrs = [[NSArray alloc] initWithArray:tempArray];
1774         [tempArray release];
1775     }
1776     if (passwordFieldAttrs == nil) {
1777         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1778         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1779         [tempArray addObject:NSAccessibilityRequiredAttribute];
1780         [tempArray addObject:NSAccessibilityInvalidAttribute];
1781         [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1782         [tempArray addObject:NSAccessibilityValueAutofilledAttribute];
1783         passwordFieldAttrs = [[NSArray alloc] initWithArray:tempArray];
1784         [tempArray release];
1785     }
1786     if (tabListAttrs == nil) {
1787         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1788         [tempArray addObject:NSAccessibilityTabsAttribute];
1789         [tempArray addObject:NSAccessibilityContentsAttribute];
1790         [tempArray addObject:NSAccessibilityOrientationAttribute];
1791         tabListAttrs = [[NSArray alloc] initWithArray:tempArray];
1792         [tempArray release];
1793     }
1794     if (outlineAttrs == nil) {
1795         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1796         [tempArray addObject:NSAccessibilitySelectedRowsAttribute];
1797         [tempArray addObject:NSAccessibilityRowsAttribute];
1798         [tempArray addObject:NSAccessibilityColumnsAttribute];
1799         [tempArray addObject:NSAccessibilityOrientationAttribute];
1800         outlineAttrs = [[NSArray alloc] initWithArray:tempArray];
1801         [tempArray release];
1802     }
1803     if (outlineRowAttrs == nil) {
1804         tempArray = [[NSMutableArray alloc] initWithArray:tableRowAttrs];
1805         [tempArray addObject:NSAccessibilityDisclosingAttribute];
1806         [tempArray addObject:NSAccessibilityDisclosedByRowAttribute];
1807         [tempArray addObject:NSAccessibilityDisclosureLevelAttribute];
1808         [tempArray addObject:NSAccessibilityDisclosedRowsAttribute];
1809         outlineRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1810         [tempArray release];
1811     }
1812     if (scrollViewAttrs == nil) {
1813         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1814         [tempArray addObject:NSAccessibilityContentsAttribute];
1815         [tempArray addObject:NSAccessibilityHorizontalScrollBarAttribute];
1816         [tempArray addObject:NSAccessibilityVerticalScrollBarAttribute];
1817         scrollViewAttrs = [[NSArray alloc] initWithArray:tempArray];
1818         [tempArray release];
1819     }
1820
1821     NSArray *objectAttributes = attributes;
1822
1823     if (backingObject->isPasswordField())
1824         objectAttributes = passwordFieldAttrs;
1825     else if (backingObject->isWebArea())
1826         objectAttributes = webAreaAttrs;
1827     else if (backingObject->isTextControl())
1828         objectAttributes = textAttrs;
1829     else if (backingObject->isLink() || backingObject->isImage())
1830         objectAttributes = anchorAttrs;
1831     else if (backingObject->isTable() && backingObject->isExposable())
1832         objectAttributes = tableAttrs;
1833     else if (backingObject->isTableColumn())
1834         objectAttributes = tableColAttrs;
1835     else if (backingObject->isTableCell())
1836         objectAttributes = tableCellAttrs;
1837     else if (backingObject->isTableRow()) {
1838         // An ARIA table row can be collapsed and expanded, so it needs the extra attributes.
1839         if (backingObject->isARIATreeGridRow())
1840             objectAttributes = outlineRowAttrs;
1841         else
1842             objectAttributes = tableRowAttrs;
1843     } else if (backingObject->isTree())
1844         objectAttributes = outlineAttrs;
1845     else if (backingObject->isTreeItem())
1846         objectAttributes = outlineRowAttrs;
1847     else if (backingObject->isListBox())
1848         objectAttributes = listBoxAttrs;
1849     else if (backingObject->isList())
1850         objectAttributes = listAttrs;
1851     else if (backingObject->isComboBox())
1852         objectAttributes = comboBoxAttrs;
1853     else if (backingObject->isProgressIndicator() || backingObject->isSlider())
1854         objectAttributes = rangeAttrs;
1855     // These are processed in order because an input image is a button, and a button is a control.
1856     else if (backingObject->isInputImage())
1857         objectAttributes = inputImageAttrs;
1858     else if (backingObject->isButton())
1859         objectAttributes = buttonAttrs;
1860     else if (backingObject->isControl())
1861         objectAttributes = controlAttrs;
1862
1863     else if (backingObject->isGroup() || backingObject->isListItem())
1864         objectAttributes = groupAttrs;
1865     else if (backingObject->isTabList())
1866         objectAttributes = tabListAttrs;
1867     else if (backingObject->isScrollView())
1868         objectAttributes = scrollViewAttrs;
1869     else if (backingObject->isSpinButton())
1870         objectAttributes = incrementorAttrs;
1871     else if (backingObject->isMenu())
1872         objectAttributes = menuAttrs;
1873     else if (backingObject->isMenuBar())
1874         objectAttributes = menuBarAttrs;
1875     else if (backingObject->isMenuButton())
1876         objectAttributes = menuButtonAttrs;
1877     else if (backingObject->isMenuItem())
1878         objectAttributes = menuItemAttrs;
1879
1880     NSArray *additionalAttributes = [self additionalAccessibilityAttributeNames];
1881     if ([additionalAttributes count])
1882         objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:additionalAttributes];
1883
1884     // Only expose AXARIACurrent attribute when the element is set to be current item.
1885     if (backingObject->currentState() != AccessibilityCurrentState::False)
1886         objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:@[ NSAccessibilityARIACurrentAttribute ]];
1887
1888     // AppKit needs to know the screen height in order to do the coordinate conversion.
1889     objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:@[ NSAccessibilityPrimaryScreenHeightAttribute ]];
1890
1891     return objectAttributes;
1892 }
1893
1894 - (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(id)textMarkerRange
1895 {
1896     if (!textMarkerRange)
1897         return VisiblePositionRange();
1898     AXObjectCache* cache = self.axBackingObject->axObjectCache();
1899     return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(cache, textMarkerRange), visiblePositionForEndOfTextMarkerRange(cache, textMarkerRange));
1900 }
1901
1902 - (NSArray*)renderWidgetChildren
1903 {
1904     return Accessibility::retrieveValueFromMainThread<NSArray *>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> NSArray * {
1905         auto* backingObject = protectedSelf.get().axBackingObject;
1906         if (!backingObject)
1907             return nil;
1908
1909         Widget* widget = backingObject->widget();
1910         if (!widget)
1911             return nil;
1912         ALLOW_DEPRECATED_DECLARATIONS_BEGIN
1913         return [(widget->platformWidget()) accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
1914         ALLOW_DEPRECATED_DECLARATIONS_END
1915     });
1916 }
1917
1918 - (id)remoteAccessibilityParentObject
1919 {
1920     ASSERT(isMainThread());
1921     if (!self.axBackingObject)
1922         return nil;
1923
1924     if (auto* document = self.axBackingObject->document()) {
1925         if (auto* frame = document->frame())
1926             return frame->loader().client().accessibilityRemoteObject();
1927     }
1928
1929     return nil;
1930 }
1931
1932 static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector)
1933 {
1934     unsigned length = [array count];
1935     vector.reserveInitialCapacity(length);
1936     for (unsigned i = 0; i < length; ++i) {
1937         AXCoreObject* obj = [[array objectAtIndex:i] axBackingObject];
1938         if (obj)
1939             vector.append(obj);
1940     }
1941 }
1942
1943 static NSMutableArray *convertStringsToNSArray(const Vector<String>& vector)
1944 {
1945     NSMutableArray *array = [NSMutableArray arrayWithCapacity:vector.size()];
1946     for (const auto& string : vector)
1947         [array addObject:string];
1948     return array;
1949 }
1950
1951 - (id)textMarkerRangeForSelection
1952 {
1953     VisibleSelection selection = self.axBackingObject->selection();
1954     if (selection.isNone())
1955         return nil;
1956     return [self textMarkerRangeFromVisiblePositions:selection.visibleStart() endPosition:selection.visibleEnd()];
1957 }
1958
1959 - (id)associatedPluginParent
1960 {
1961     return Accessibility::retrieveAutoreleasedValueFromMainThread<id>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> RetainPtr<id> {
1962         auto* backingObject = protectedSelf.get().axBackingObject;
1963         if (!backingObject || !backingObject->hasApplePDFAnnotationAttribute())
1964             return nil;
1965
1966         if (!backingObject->document()->isPluginDocument())
1967             return nil;
1968
1969         Widget* pluginWidget = static_cast<PluginDocument*>(backingObject->document())->pluginWidget();
1970         if (!pluginWidget || !pluginWidget->isPluginViewBase())
1971             return nil;
1972
1973         return static_cast<PluginViewBase*>(pluginWidget)->accessibilityAssociatedPluginParentForElement(backingObject->element());
1974     });
1975 }
1976
1977 static void WebTransformCGPathToNSBezierPath(void* info, const CGPathElement *element)
1978 {
1979     NSBezierPath *bezierPath = (__bridge NSBezierPath *)info;
1980     switch (element->type) {
1981     case kCGPathElementMoveToPoint:
1982         [bezierPath moveToPoint:NSPointFromCGPoint(element->points[0])];
1983         break;
1984     case kCGPathElementAddLineToPoint:
1985         [bezierPath lineToPoint:NSPointFromCGPoint(element->points[0])];
1986         break;
1987     case kCGPathElementAddCurveToPoint:
1988         [bezierPath curveToPoint:NSPointFromCGPoint(element->points[0]) controlPoint1:NSPointFromCGPoint(element->points[1]) controlPoint2:NSPointFromCGPoint(element->points[2])];
1989         break;
1990     case kCGPathElementCloseSubpath:
1991         [bezierPath closePath];
1992         break;
1993     default:
1994         break;
1995     }
1996 }
1997
1998 - (NSBezierPath *)bezierPathFromPath:(CGPathRef)path
1999 {
2000     NSBezierPath *bezierPath = [NSBezierPath bezierPath];
2001     CGPathApply(path, (__bridge void*)bezierPath, WebTransformCGPathToNSBezierPath);
2002     return bezierPath;
2003 }
2004
2005 - (NSBezierPath *)path
2006 {
2007     Path path = self.axBackingObject->elementPath();
2008     if (path.isEmpty())
2009         return NULL;
2010     
2011     CGPathRef transformedPath = [self convertPathToScreenSpace:path];
2012     return [self bezierPathFromPath:transformedPath];
2013 }
2014
2015 - (NSNumber *)primaryScreenHeight
2016 {
2017     FloatRect screenRect = screenRectForPrimaryScreen();
2018     return [NSNumber numberWithFloat:screenRect.height()];
2019 }
2020
2021 - (size_t)childrenVectorSize
2022 {
2023     return self.axBackingObject->children().size();
2024 }
2025
2026 - (NSArray<WebAccessibilityObjectWrapper *> *)childrenVectorArray
2027 {
2028     return convertToNSArray(self.axBackingObject->children());
2029 }
2030
2031 - (NSValue *)position
2032 {
2033 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
2034     if (_AXUIElementRequestServicedBySecondaryAXThread())
2035         return [NSValue valueWithPoint:(NSPoint)self.axBackingObject->relativeFrame().location()];
2036 #endif
2037         
2038     auto rect = snappedIntRect(self.axBackingObject->elementRect());
2039     
2040     // The Cocoa accessibility API wants the lower-left corner.
2041     auto floatPoint = FloatPoint(rect.x(), rect.maxY());
2042
2043     auto floatRect = FloatRect(floatPoint, FloatSize());
2044     CGPoint cgPoint = [self convertRectToSpace:floatRect space:AccessibilityConversionSpace::Screen].origin;
2045     return [NSValue valueWithPoint:NSPointFromCGPoint(cgPoint)];
2046 }
2047
2048 - (NSString*)role
2049 {
2050     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
2051     if (self.axBackingObject->isAttachment())
2052         return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute];
2053     ALLOW_DEPRECATED_DECLARATIONS_END
2054
2055     NSString *string = self.axBackingObject->rolePlatformString();
2056     if (string.length)
2057         return string;
2058     return NSAccessibilityUnknownRole;
2059 }
2060
2061 ALLOW_DEPRECATED_DECLARATIONS_BEGIN
2062 - (NSString*)subrole
2063 {
2064     if (self.axBackingObject->isPasswordField())
2065         return NSAccessibilitySecureTextFieldSubrole;
2066     if (self.axBackingObject->isSearchField())
2067         return NSAccessibilitySearchFieldSubrole;
2068     
2069     if (self.axBackingObject->isAttachment()) {
2070         NSView* attachView = [self attachmentView];
2071         if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute])
2072             return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute];
2073     }
2074     
2075     if (self.axBackingObject->isMeter())
2076         return @"AXMeter";
2077     
2078     AccessibilityRole role = self.axBackingObject->roleValue();
2079     if (role == AccessibilityRole::HorizontalRule)
2080         return NSAccessibilityContentSeparatorSubrole;
2081     if (role == AccessibilityRole::ToggleButton)
2082         return NSAccessibilityToggleSubrole;
2083     if (role == AccessibilityRole::Footer)
2084         return @"AXFooter";
2085
2086     if (self.axBackingObject->roleValue() == AccessibilityRole::SpinButtonPart) {
2087         if (self.axBackingObject->isIncrementor())
2088             return NSAccessibilityIncrementArrowSubrole;
2089         return NSAccessibilityDecrementArrowSubrole;
2090     }
2091     
2092     if (self.axBackingObject->isFileUploadButton())
2093         return @"AXFileUploadButton";
2094     
2095     if (self.axBackingObject->isTreeItem())
2096         return NSAccessibilityOutlineRowSubrole;
2097     
2098     if (self.axBackingObject->isFieldset())
2099         return @"AXFieldset";
2100
2101     if (self.axBackingObject->isList()) {
2102         if (self.axBackingObject->isUnorderedList() || self.axBackingObject->isOrderedList())
2103             return NSAccessibilityContentListSubrole;
2104         if (self.axBackingObject->isDescriptionList()) {
2105             return NSAccessibilityDescriptionListSubrole;
2106         }
2107     }
2108
2109     // ARIA content subroles.
2110     switch (role) {
2111     case AccessibilityRole::LandmarkBanner:
2112         return @"AXLandmarkBanner";
2113     case AccessibilityRole::LandmarkComplementary:
2114         return @"AXLandmarkComplementary";
2115     case AccessibilityRole::LandmarkContentInfo:
2116         return @"AXLandmarkContentInfo";
2117     case AccessibilityRole::LandmarkMain:
2118         return @"AXLandmarkMain";
2119     case AccessibilityRole::LandmarkNavigation:
2120         return @"AXLandmarkNavigation";
2121     case AccessibilityRole::LandmarkDocRegion:
2122     case AccessibilityRole::LandmarkRegion:
2123         return @"AXLandmarkRegion";
2124     case AccessibilityRole::LandmarkSearch:
2125         return @"AXLandmarkSearch";
2126     case AccessibilityRole::ApplicationAlert:
2127         return @"AXApplicationAlert";
2128     case AccessibilityRole::ApplicationAlertDialog:
2129         return @"AXApplicationAlertDialog";
2130     case AccessibilityRole::ApplicationDialog:
2131         return @"AXApplicationDialog";
2132     case AccessibilityRole::ApplicationGroup:
2133     case AccessibilityRole::ApplicationTextGroup:
2134     case AccessibilityRole::Feed:
2135     case AccessibilityRole::Footnote:
2136         return @"AXApplicationGroup";
2137     case AccessibilityRole::ApplicationLog:
2138         return @"AXApplicationLog";
2139     case AccessibilityRole::ApplicationMarquee:
2140         return @"AXApplicationMarquee";
2141     case AccessibilityRole::ApplicationStatus:
2142         return @"AXApplicationStatus";
2143     case AccessibilityRole::ApplicationTimer:
2144         return @"AXApplicationTimer";
2145     case AccessibilityRole::Document:
2146     case AccessibilityRole::GraphicsDocument:
2147         return @"AXDocument";
2148     case AccessibilityRole::DocumentArticle:
2149         return @"AXDocumentArticle";
2150     case AccessibilityRole::DocumentMath:
2151         return @"AXDocumentMath";
2152     case AccessibilityRole::DocumentNote:
2153         return @"AXDocumentNote";
2154     case AccessibilityRole::UserInterfaceTooltip:
2155         return @"AXUserInterfaceTooltip";
2156     case AccessibilityRole::TabPanel:
2157         return @"AXTabPanel";
2158     case AccessibilityRole::Definition:
2159         return @"AXDefinition";
2160     case AccessibilityRole::DescriptionListTerm:
2161     case AccessibilityRole::Term:
2162         return @"AXTerm";
2163     case AccessibilityRole::DescriptionListDetail:
2164         return @"AXDescription";
2165     case AccessibilityRole::WebApplication:
2166         return @"AXWebApplication";
2167         // Default doesn't return anything, so roles defined below can be chosen.
2168     default:
2169         break;
2170     }
2171     
2172     if (role == AccessibilityRole::MathElement) {
2173         if (self.axBackingObject->isMathFraction())
2174             return @"AXMathFraction";
2175         if (self.axBackingObject->isMathFenced())
2176             return @"AXMathFenced";
2177         if (self.axBackingObject->isMathSubscriptSuperscript())
2178             return @"AXMathSubscriptSuperscript";
2179         if (self.axBackingObject->isMathRow())
2180             return @"AXMathRow";
2181         if (self.axBackingObject->isMathUnderOver())
2182             return @"AXMathUnderOver";
2183         if (self.axBackingObject->isMathSquareRoot())
2184             return @"AXMathSquareRoot";
2185         if (self.axBackingObject->isMathRoot())
2186             return @"AXMathRoot";
2187         if (self.axBackingObject->isMathText())
2188             return @"AXMathText";
2189         if (self.axBackingObject->isMathNumber())
2190             return @"AXMathNumber";
2191         if (self.axBackingObject->isMathIdentifier())
2192             return @"AXMathIdentifier";
2193         if (self.axBackingObject->isMathTable())
2194             return @"AXMathTable";
2195         if (self.axBackingObject->isMathTableRow())
2196             return @"AXMathTableRow";
2197         if (self.axBackingObject->isMathTableCell())
2198             return @"AXMathTableCell";
2199         if (self.axBackingObject->isMathFenceOperator())
2200             return @"AXMathFenceOperator";
2201         if (self.axBackingObject->isMathSeparatorOperator())
2202             return @"AXMathSeparatorOperator";
2203         if (self.axBackingObject->isMathOperator())
2204             return @"AXMathOperator";
2205         if (self.axBackingObject->isMathMultiscript())
2206             return @"AXMathMultiscript";
2207     }
2208     
2209     if (role == AccessibilityRole::Video)
2210         return @"AXVideo";
2211     if (role == AccessibilityRole::Audio)
2212         return @"AXAudio";
2213     if (role == AccessibilityRole::Details)
2214         return @"AXDetails";
2215     if (role == AccessibilityRole::Summary)
2216         return @"AXSummary";
2217     if (role == AccessibilityRole::Time)
2218         return @"AXTimeGroup";
2219
2220     if (self.axBackingObject->isMediaTimeline())
2221         return NSAccessibilityTimelineSubrole;
2222
2223     if (self.axBackingObject->isSwitch())
2224         return NSAccessibilitySwitchSubrole;
2225
2226     if (role == AccessibilityRole::Insertion)
2227         return @"AXInsertStyleGroup";
2228     if (role == AccessibilityRole::Deletion)
2229         return @"AXDeleteStyleGroup";
2230     if (role == AccessibilityRole::Superscript)
2231         return @"AXSuperscriptStyleGroup";
2232     if (role == AccessibilityRole::Subscript)
2233         return @"AXSubscriptStyleGroup";
2234
2235     if (self.axBackingObject->isStyleFormatGroup()) {
2236         auto tagName = self.axBackingObject->tagName();
2237         if (tagName == kbdTag)
2238             return @"AXKeyboardInputStyleGroup";
2239         if (tagName == codeTag)
2240             return @"AXCodeStyleGroup";
2241         if (tagName == preTag)
2242             return @"AXPreformattedStyleGroup";
2243         if (tagName == sampTag)
2244             return @"AXSampleStyleGroup";
2245         if (tagName == varTag)
2246             return @"AXVariableStyleGroup";
2247         if (tagName == citeTag)
2248             return @"AXCiteStyleGroup";
2249         ASSERT_NOT_REACHED();
2250     }
2251     
2252     // Ruby subroles
2253     switch (role) {
2254     case AccessibilityRole::RubyBase:
2255         return NSAccessibilityRubyBaseSubrole;
2256     case AccessibilityRole::RubyBlock:
2257         return NSAccessibilityRubyBlockSubrole;
2258     case AccessibilityRole::RubyInline:
2259         return NSAccessibilityRubyInlineSubrole;
2260     case AccessibilityRole::RubyRun:
2261         return NSAccessibilityRubyRunSubrole;
2262     case AccessibilityRole::RubyText:
2263         return NSAccessibilityRubyTextSubrole;
2264     default:
2265         break;
2266     }
2267     
2268     return nil;
2269 }
2270 ALLOW_DEPRECATED_DECLARATIONS_END
2271
2272 - (NSString*)roleDescription
2273 {
2274     if (!self.axBackingObject)
2275         return nil;
2276
2277     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
2278     // attachments have the AXImage role, but a different subrole
2279     if (self.axBackingObject->isAttachment())
2280         return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute];
2281     ALLOW_DEPRECATED_DECLARATIONS_END
2282
2283     String roleDescription = self.axBackingObject->roleDescription();
2284     if (!roleDescription.isEmpty())
2285         return roleDescription;
2286
2287     NSString *axRole = self.axBackingObject->rolePlatformString();
2288     // Fallback to the system default role description.
2289     // If we get the same string back, then as a last resort, return unknown.
2290     NSString *defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]);
2291
2292     // On earlier Mac versions (Lion), using a non-standard subrole would result in a role description
2293     // being returned that looked like AXRole:AXSubrole. To make all platforms have the same role descriptions
2294     // we should fallback on a role description ignoring the subrole in these cases.
2295     if ([defaultRoleDescription isEqualToString:[NSString stringWithFormat:@"%@:%@", axRole, [self subrole]]])
2296         defaultRoleDescription = NSAccessibilityRoleDescription(axRole, nil);
2297     
2298     if (![defaultRoleDescription isEqualToString:axRole])
2299         return defaultRoleDescription;
2300     
2301     return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);
2302 }
2303
2304 - (NSString *)computedRoleString
2305 {
2306     if (!self.axBackingObject)
2307         return nil;
2308     return self.axBackingObject->computedRoleString();
2309 }
2310
2311 - (id)scrollViewParent
2312 {
2313     return Accessibility::retrieveAutoreleasedValueFromMainThread<id>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> RetainPtr<id> {
2314         if (!is<AccessibilityScrollView>(protectedSelf.get().axBackingObject))
2315             return nil;
2316
2317         // If this scroll view provides it's parent object (because it's a sub-frame), then
2318         // we should not find the remoteAccessibilityParent.
2319         if (protectedSelf.get().axBackingObject->parentObject())
2320             return nil;
2321
2322         ScrollView* scroll = downcast<AccessibilityScrollView>(*protectedSelf.get().axBackingObject).scrollView();
2323         if (!scroll)
2324             return nil;
2325
2326         if (scroll->platformWidget())
2327             return NSAccessibilityUnignoredAncestor(scroll->platformWidget());
2328
2329         return [protectedSelf remoteAccessibilityParentObject];
2330     });
2331 }
2332
2333 - (id)windowElement:(NSString*)attributeName
2334 {
2335     return Accessibility::retrieveAutoreleasedValueFromMainThread<id>([attributeName, protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> RetainPtr<id> {
2336         id remoteParent = [protectedSelf remoteAccessibilityParentObject];
2337         if (remoteParent) {
2338             ALLOW_DEPRECATED_DECLARATIONS_BEGIN
2339             return [remoteParent accessibilityAttributeValue:attributeName];
2340             ALLOW_DEPRECATED_DECLARATIONS_END
2341         }
2342
2343         auto* backingObject = protectedSelf.get().axBackingObject;
2344         if (!backingObject)
2345             return nil;
2346
2347         if (auto* fv = backingObject->documentFrameView())
2348             return [fv->platformWidget() window];
2349
2350         return nil;
2351     });
2352 }
2353
2354 // FIXME: split up this function in a better way.
2355 // suggestions: Use a hash table that maps attribute names to function calls,
2356 // or maybe pointers to member functions
2357 ALLOW_DEPRECATED_IMPLEMENTATIONS_BEGIN
2358 - (id)accessibilityAttributeValue:(NSString*)attributeName
2359 ALLOW_DEPRECATED_IMPLEMENTATIONS_END
2360 {
2361     auto* backingObject = self.updateObjectBackingStore;
2362     if (!backingObject)
2363         return nil;
2364
2365     if (backingObject->isDetachedFromParent())
2366         return nil;
2367
2368     if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])
2369         return [self role];
2370
2371     if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute])
2372         return [self subrole];
2373
2374     if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])
2375         return [self roleDescription];
2376
2377     // AXARIARole is only used by DumpRenderTree (so far).
2378     if ([attributeName isEqualToString:@"AXARIARole"])
2379         return [self computedRoleString];
2380
2381     if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {
2382
2383         // This will return the parent of the AXWebArea, if this is a web area.
2384         id scrollViewParent = [self scrollViewParent];
2385         if (scrollViewParent)
2386             return scrollViewParent;
2387
2388         // Tree item (changed to AXRows) can only report the tree (AXOutline) as its parent.
2389         if (backingObject->isTreeItem()) {
2390             auto parent = backingObject->parentObjectUnignored();
2391             while (parent) {
2392                 if (parent->isTree())
2393                     return parent->wrapper();
2394                 parent = parent->parentObjectUnignored();
2395             }
2396         }
2397
2398         auto parent = backingObject->parentObjectUnignored();
2399         if (!parent)
2400             return nil;
2401
2402         // In WebKit1, the scroll view is provided by the system (the attachment view), so the parent
2403         // should be reported directly as such.
2404         if (backingObject->isWebArea() && parent->isAttachment())
2405             return [parent->wrapper() attachmentView];
2406
2407         return parent->wrapper();
2408     }
2409
2410     if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute] || [attributeName isEqualToString: NSAccessibilityChildrenInNavigationOrderAttribute]) {
2411         if (!self.childrenVectorSize) {
2412             NSArray* children = [self renderWidgetChildren];
2413             if (children != nil)
2414                 return children;
2415         }
2416
2417         // The tree's (AXOutline) children are supposed to be its rows and columns.
2418         // The ARIA spec doesn't have columns, so we just need rows.
2419         if (backingObject->isTree())
2420             return [self accessibilityAttributeValue:NSAccessibilityRowsAttribute];
2421
2422         // A tree item should only expose its content as its children (not its rows)
2423         if (backingObject->isTreeItem()) {
2424             AccessibilityObject::AccessibilityChildrenVector contentCopy;
2425             backingObject->ariaTreeItemContent(contentCopy);
2426             return convertToNSArray(contentCopy);
2427         }
2428
2429         return self.childrenVectorArray;
2430     }
2431
2432     if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
2433         if (backingObject->canHaveSelectedChildren()) {
2434             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2435             backingObject->selectedChildren(selectedChildrenCopy);
2436             return convertToNSArray(selectedChildrenCopy);
2437         }
2438         return nil;
2439     }
2440
2441     if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) {
2442         if (backingObject->isListBox()) {
2443             AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy;
2444             backingObject->visibleChildren(visibleChildrenCopy);
2445             return convertToNSArray(visibleChildrenCopy);
2446         }
2447
2448         if (backingObject->isList())
2449             return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
2450
2451         return nil;
2452     }
2453
2454
2455     if (backingObject->isWebArea()) {
2456         if ([attributeName isEqualToString:@"AXLinkUIElements"]) {
2457             AccessibilityObject::AccessibilityChildrenVector links;
2458             downcast<AccessibilityRenderObject>(*backingObject).getDocumentLinks(links);
2459             return convertToNSArray(links);
2460         }
2461         if ([attributeName isEqualToString:@"AXLoaded"])
2462             return [NSNumber numberWithBool:backingObject->isLoaded()];
2463         if ([attributeName isEqualToString:@"AXLayoutCount"])
2464             return [NSNumber numberWithInt:backingObject->layoutCount()];
2465         if ([attributeName isEqualToString:NSAccessibilityLoadingProgressAttribute])
2466             return [NSNumber numberWithDouble:backingObject->estimatedLoadingProgress()];
2467         if ([attributeName isEqualToString:NSAccessibilityPreventKeyboardDOMEventDispatchAttribute])
2468             return [NSNumber numberWithBool:backingObject->preventKeyboardDOMEventDispatch()];
2469         if ([attributeName isEqualToString:NSAccessibilityCaretBrowsingEnabledAttribute])
2470             return [NSNumber numberWithBool:backingObject->caretBrowsingEnabled()];
2471         if ([attributeName isEqualToString:NSAccessibilityWebSessionIDAttribute])
2472             return @(backingObject->sessionID());
2473     }
2474
2475     if (backingObject->isTextControl()) {
2476         if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) {
2477             int length = backingObject->textLength();
2478             if (length < 0)
2479                 return nil;
2480             return [NSNumber numberWithUnsignedInt:length];
2481         }
2482         if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
2483             String selectedText = backingObject->selectedText();
2484             if (selectedText.isNull())
2485                 return nil;
2486             return (NSString*)selectedText;
2487         }
2488         if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
2489             PlainTextRange textRange = backingObject->selectedTextRange();
2490             return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)];
2491         }
2492         // TODO: Get actual visible range. <rdar://problem/4712101>
2493         if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
2494             return backingObject->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, backingObject->textLength())];
2495         if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) {
2496             // if selectionEnd > 0, then there is selected text and this question should not be answered
2497             if (backingObject->isPasswordField() || backingObject->selectionEnd() > 0)
2498                 return nil;
2499
2500             auto focusedObject = downcast<AccessibilityObject>(backingObject->focusedUIElement());
2501             if (focusedObject != backingObject)
2502                 return nil;
2503
2504             VisiblePosition focusedPosition = focusedObject->visiblePositionForIndex(focusedObject->selectionStart(), true);
2505             int lineNumber = backingObject->lineForPosition(focusedPosition);
2506             if (lineNumber < 0)
2507                 return nil;
2508
2509             return [NSNumber numberWithInt:lineNumber];
2510         }
2511     }
2512
2513     if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {
2514         URL url = backingObject->url();
2515         if (url.isNull())
2516             return nil;
2517         return (NSURL*)url;
2518     }
2519
2520     if ([attributeName isEqualToString:NSAccessibilityIncrementButtonAttribute]) {
2521         auto incrementButton = backingObject->incrementButton();
2522         return incrementButton ? incrementButton->wrapper() : nil;
2523     }
2524
2525     if ([attributeName isEqualToString:NSAccessibilityDecrementButtonAttribute]) {
2526         auto decrementButton = backingObject->decrementButton();
2527         return decrementButton ? decrementButton->wrapper() : nil;
2528     }
2529
2530     if ([attributeName isEqualToString: @"AXVisited"])
2531         return [NSNumber numberWithBool: backingObject->isVisited()];
2532
2533     if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) {
2534         if (backingObject->isAttachment()) {
2535             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute])
2536                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute];
2537         }
2538
2539         // Meter elements should communicate their content via AXValueDescription.
2540         if (backingObject->isMeter())
2541             return [NSString string];
2542
2543         // Summary element should use its text node as AXTitle.
2544         if (backingObject->isSummary())
2545             return backingObject->textUnderElement();
2546
2547         return [self baseAccessibilityTitle];
2548     }
2549
2550     if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) {
2551         if (backingObject->isAttachment()) {
2552             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute])
2553                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute];
2554         }
2555         return [self baseAccessibilityDescription];
2556     }
2557
2558     if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
2559         if (backingObject->isAttachment()) {
2560             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute])
2561                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute];
2562         }
2563         if (backingObject->supportsRangeValue())
2564             return [NSNumber numberWithFloat:backingObject->valueForRange()];
2565         if (backingObject->roleValue() == AccessibilityRole::SliderThumb)
2566             return [NSNumber numberWithFloat:backingObject->parentObject()->valueForRange()];
2567         if (backingObject->isHeading())
2568             return [NSNumber numberWithInt:backingObject->headingLevel()];
2569
2570         if (backingObject->isCheckboxOrRadio() || backingObject->isMenuItem() || backingObject->isSwitch() || backingObject->isToggleButton()) {
2571             switch (backingObject->checkboxOrRadioValue()) {
2572             case AccessibilityButtonState::Off:
2573                 return [NSNumber numberWithInt:0];
2574             case AccessibilityButtonState::On:
2575                 return [NSNumber numberWithInt:1];
2576             case AccessibilityButtonState::Mixed:
2577                 return [NSNumber numberWithInt:2];
2578             }
2579         }
2580
2581         // radio groups return the selected radio button as the AXValue
2582         if (backingObject->isRadioGroup()) {
2583             AXCoreObject* radioButton = backingObject->selectedRadioButton();
2584             if (!radioButton)
2585                 return nil;
2586             return radioButton->wrapper();
2587         }
2588
2589         if (backingObject->isTabList()) {
2590             AXCoreObject* tabItem = backingObject->selectedTabItem();
2591             if (!tabItem)
2592                 return nil;
2593             return tabItem->wrapper();
2594         }
2595
2596         if (backingObject->isTabItem())
2597             return [NSNumber numberWithInt:backingObject->isSelected()];
2598
2599         if (backingObject->isColorWell()) {
2600             int r, g, b;
2601             backingObject->colorValue(r, g, b);
2602             return [NSString stringWithFormat:@"rgb %7.5f %7.5f %7.5f 1", r / 255., g / 255., b / 255.];
2603         }
2604
2605         return backingObject->stringValue();
2606     }
2607
2608     if ([attributeName isEqualToString:(NSString *)kAXMenuItemMarkCharAttribute]) {
2609         const unichar ch = 0x2713; // ✓ used on Mac for selected menu items.
2610         return (backingObject->isChecked()) ? [NSString stringWithCharacters:&ch length:1] : nil;
2611     }
2612
2613     if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute]) {
2614         // Indeterminate progress indicator should return 0.
2615         if (backingObject->ariaRoleAttribute() == AccessibilityRole::ProgressIndicator && !backingObject->hasARIAValueNow())
2616             return @0;
2617         return [NSNumber numberWithFloat:backingObject->minValueForRange()];
2618     }
2619
2620     if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute]) {
2621         // Indeterminate progress indicator should return 0.
2622         if (backingObject->ariaRoleAttribute() == AccessibilityRole::ProgressIndicator && !backingObject->hasARIAValueNow())
2623             return @0;
2624         return [NSNumber numberWithFloat:backingObject->maxValueForRange()];
2625     }
2626
2627     if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])
2628         return [self baseAccessibilityHelpText];
2629
2630     if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2631         return [NSNumber numberWithBool: backingObject->isFocused()];
2632
2633     if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])
2634         return [NSNumber numberWithBool: backingObject->isEnabled()];
2635
2636     if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) {
2637         IntSize s = snappedIntRect(backingObject->elementRect()).size();
2638         return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())];
2639     }
2640
2641     if ([attributeName isEqualToString: NSAccessibilityPrimaryScreenHeightAttribute])
2642         return [self primaryScreenHeight];
2643     if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])
2644         return [self position];
2645     if ([attributeName isEqualToString:NSAccessibilityPathAttribute])
2646         return [self path];
2647
2648     if ([attributeName isEqualToString:NSAccessibilityWindowAttribute]
2649         || [attributeName isEqualToString:NSAccessibilityTopLevelUIElementAttribute])
2650         return [self windowElement:attributeName];
2651
2652     if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) {
2653         AtomString accessKey = backingObject->accessKey();
2654         if (accessKey.isNull())
2655             return nil;
2656         return accessKey;
2657     }
2658
2659     if ([attributeName isEqualToString:NSAccessibilityLinkRelationshipTypeAttribute])
2660         return backingObject->linkRelValue();
2661
2662     if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) {
2663         if (backingObject->isTabList()) {
2664             AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2665             backingObject->tabChildren(tabsChildren);
2666             return convertToNSArray(tabsChildren);
2667         }
2668     }
2669
2670     if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) {
2671         // The contents of a tab list are all the children except the tabs.
2672         if (backingObject->isTabList()) {
2673             auto children = self.childrenVectorArray;
2674             AccessibilityObject::AccessibilityChildrenVector tabs;
2675             backingObject->tabChildren(tabs);
2676             auto tabsChildren = convertToNSArray(tabs);
2677
2678             NSMutableArray *contents = [NSMutableArray array];
2679             for (id childWrapper in children) {
2680                 if ([tabsChildren containsObject:childWrapper])
2681                     [contents addObject:childWrapper];
2682             }
2683             return contents;
2684         }
2685
2686         if (backingObject->isScrollView()) {
2687             // A scrollView's contents are everything except the scroll bars.
2688             auto children = self.childrenVectorArray;
2689             NSMutableArray *contents = [NSMutableArray array];
2690
2691             for (WebAccessibilityObjectWrapper *childWrapper in children) {
2692                 if (auto backingObject = [childWrapper axBackingObject]) {
2693                     if (!backingObject->isScrollbar())
2694                         [contents addObject:childWrapper];
2695                 }
2696             }
2697             return contents;
2698         }
2699     }
2700
2701     if (backingObject->isTable() && backingObject->isExposable()) {
2702         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute])
2703             return convertToNSArray(backingObject->rows());
2704
2705         if ([attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute])
2706             return convertToNSArray(backingObject->visibleRows());
2707
2708         // TODO: distinguish between visible and non-visible columns
2709         if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute]
2710             || [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute])
2711             return convertToNSArray(backingObject->columns());
2712
2713         if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2714             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2715             backingObject->selectedChildren(selectedChildrenCopy);
2716             return convertToNSArray(selectedChildrenCopy);
2717         }
2718
2719         // HTML tables don't support these attributes.
2720         if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute]
2721             || [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute])
2722             return nil;
2723
2724         if ([attributeName isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute])
2725             return convertToNSArray(backingObject->columnHeaders());
2726
2727         if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2728             auto* headerContainer = backingObject->headerContainer();
2729             return headerContainer ? headerContainer->wrapper() : nil;
2730         }
2731
2732         if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute])
2733             return convertToNSArray(backingObject->rowHeaders());
2734
2735         if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute])
2736             return convertToNSArray(backingObject->cells());
2737
2738         if ([attributeName isEqualToString:NSAccessibilityColumnCountAttribute])
2739             return @(backingObject->columnCount());
2740
2741         if ([attributeName isEqualToString:NSAccessibilityRowCountAttribute])
2742             return @(backingObject->rowCount());
2743
2744         if ([attributeName isEqualToString:NSAccessibilityARIAColumnCountAttribute])
2745             return @(backingObject->axColumnCount());
2746
2747         if ([attributeName isEqualToString:NSAccessibilityARIARowCountAttribute])
2748             return @(backingObject->axRowCount());
2749     }
2750
2751     if (backingObject->isTableColumn()) {
2752         if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2753             return [NSNumber numberWithUnsignedInt:backingObject->columnIndex()];
2754
2755         // rows attribute for a column is the list of all the elements in that column at each row
2756         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]
2757             || [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute])
2758             return convertToNSArray(backingObject->children());
2759
2760         if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2761             auto* header = backingObject->columnHeader();
2762             return header ? header->wrapper() : nil;
2763         }
2764     }
2765
2766     if (backingObject->isTableCell()) {
2767         if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) {
2768             auto rowRange = backingObject->rowIndexRange();
2769             return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)];
2770         }
2771
2772         if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) {
2773             auto columnRange = backingObject->columnIndexRange();
2774             return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)];
2775         }
2776
2777         if ([attributeName isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute])
2778             return convertToNSArray(backingObject->columnHeaders());
2779
2780         if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute])
2781             return convertToNSArray(backingObject->rowHeaders());
2782
2783         if ([attributeName isEqualToString:NSAccessibilityARIAColumnIndexAttribute])
2784             return @(backingObject->axColumnIndex());
2785
2786         if ([attributeName isEqualToString:NSAccessibilityARIARowIndexAttribute])
2787             return @(backingObject->axRowIndex());
2788     }
2789
2790     if (backingObject->isTree()) {
2791         if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2792             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2793             backingObject->selectedChildren(selectedChildrenCopy);
2794             return convertToNSArray(selectedChildrenCopy);
2795         }
2796         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) {
2797             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2798             backingObject->ariaTreeRows(rowsCopy);
2799             return convertToNSArray(rowsCopy);
2800         }
2801
2802         // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least.
2803         if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute])
2804             return [NSArray array];
2805     }
2806
2807     if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) {
2808         if (backingObject->isTreeItem()) {
2809             AXCoreObject* parent = backingObject->parentObject();
2810             for (; parent && !parent->isTree(); parent = parent->parentObject())
2811             { }
2812
2813             if (!parent)
2814                 return nil;
2815
2816             // Find the index of this item by iterating the parents.
2817             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2818             parent->ariaTreeRows(rowsCopy);
2819             size_t count = rowsCopy.size();
2820             for (size_t k = 0; k < count; ++k)
2821                 if (rowsCopy[k]->wrapper() == self)
2822                     return [NSNumber numberWithUnsignedInt:k];
2823
2824             return nil;
2825         }
2826
2827         if (backingObject->isTableRow())
2828             return [NSNumber numberWithInt:backingObject->rowIndex()];
2829     }
2830
2831     // The rows that are considered inside this row.
2832     if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) {
2833         if (backingObject->isTreeItem() || backingObject->isARIATreeGridRow())
2834             return convertToNSArray(backingObject->disclosedRows());
2835     }
2836
2837     // The row that contains this row. It should be the same as the first parent that is a treeitem.
2838     if ([attributeName isEqualToString:NSAccessibilityDisclosedByRowAttribute]) {
2839         if (backingObject->isTreeItem()) {
2840             AXCoreObject* parent = backingObject->parentObject();
2841             while (parent) {
2842                 if (parent->isTreeItem())
2843                     return parent->wrapper();
2844                 // If the parent is the tree itself, then this value == nil.
2845                 if (parent->isTree())
2846                     return nil;
2847                 parent = parent->parentObject();
2848             }
2849             return nil;
2850         }
2851
2852         if (backingObject->isARIATreeGridRow()) {
2853             auto* row = backingObject->disclosedByRow();
2854             return row ? row->wrapper() : nil;
2855         }
2856     }
2857
2858     if ([attributeName isEqualToString:NSAccessibilityDisclosureLevelAttribute]) {
2859         // Convert from 1-based level (from aria-level spec) to 0-based level (Mac)
2860         int level = backingObject->hierarchicalLevel();
2861         if (level > 0)
2862             level -= 1;
2863         return [NSNumber numberWithInt:level];
2864     }
2865     if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2866         return [NSNumber numberWithBool:backingObject->isExpanded()];
2867
2868     if (backingObject->isList() && [attributeName isEqualToString:NSAccessibilityOrientationAttribute])
2869         return NSAccessibilityVerticalOrientationValue;
2870
2871     if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2872         return [self textMarkerRangeForSelection];
2873
2874     if ([attributeName isEqualToString: @"AXStartTextMarker"])
2875         return [self textMarkerForVisiblePosition:startOfDocument(backingObject->document())];
2876     if ([attributeName isEqualToString: @"AXEndTextMarker"])
2877         return [self textMarkerForVisiblePosition:endOfDocument(backingObject->document())];
2878
2879     if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])
2880         return [NSNumber numberWithUnsignedInt:backingObject->blockquoteLevel()];
2881     if ([attributeName isEqualToString:@"AXTableLevel"])
2882         return [NSNumber numberWithInt:backingObject->tableLevel()];
2883
2884     if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) {
2885         AccessibilityObject::AccessibilityChildrenVector linkedUIElements;
2886         backingObject->linkedUIElements(linkedUIElements);
2887         return convertToNSArray(linkedUIElements);
2888     }
2889
2890     if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2891         return [NSNumber numberWithBool:backingObject->isSelected()];
2892
2893     if ([attributeName isEqualToString: NSAccessibilityARIACurrentAttribute])
2894         return backingObject->currentValue();
2895
2896     if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && backingObject->isMenuButton()) {
2897         AccessibilityObject* uiElement = downcast<AccessibilityRenderObject>(*backingObject).menuForMenuButton();
2898         if (uiElement)
2899             return [NSArray arrayWithObject:uiElement->wrapper()];
2900     }
2901
2902     if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
2903         if (!backingObject->exposesTitleUIElement())
2904             return nil;
2905
2906         AXCoreObject* obj = backingObject->titleUIElement();
2907         if (obj)
2908             return obj->wrapper();
2909         return nil;
2910     }
2911
2912     if ([attributeName isEqualToString:NSAccessibilityValueDescriptionAttribute])
2913         return backingObject->valueDescription();
2914
2915     if ([attributeName isEqualToString:NSAccessibilityOrientationAttribute]) {
2916         AccessibilityOrientation elementOrientation = backingObject->orientation();
2917         if (elementOrientation == AccessibilityOrientation::Vertical)
2918             return NSAccessibilityVerticalOrientationValue;
2919         if (elementOrientation == AccessibilityOrientation::Horizontal)
2920             return NSAccessibilityHorizontalOrientationValue;
2921         if (elementOrientation == AccessibilityOrientation::Undefined)
2922             return NSAccessibilityUnknownOrientationValue;
2923         return nil;
2924     }
2925
2926     if ([attributeName isEqualToString:NSAccessibilityHorizontalScrollBarAttribute]) {
2927         AXCoreObject* scrollBar = backingObject->scrollBar(AccessibilityOrientation::Horizontal);
2928         if (scrollBar)
2929             return scrollBar->wrapper();
2930         return nil;
2931     }
2932     if ([attributeName isEqualToString:NSAccessibilityVerticalScrollBarAttribute]) {
2933         AXCoreObject* scrollBar = backingObject->scrollBar(AccessibilityOrientation::Vertical);
2934         if (scrollBar)
2935             return scrollBar->wrapper();
2936         return nil;
2937     }
2938
2939     if ([attributeName isEqualToString:NSAccessibilitySortDirectionAttribute]) {
2940         switch (backingObject->sortDirection()) {
2941         case AccessibilitySortDirection::Ascending:
2942             return NSAccessibilityAscendingSortDirectionValue;
2943         case AccessibilitySortDirection::Descending:
2944             return NSAccessibilityDescendingSortDirectionValue;
2945         default:
2946             return NSAccessibilityUnknownSortDirectionValue;
2947         }
2948     }
2949
2950     if ([attributeName isEqualToString:NSAccessibilityLanguageAttribute])
2951         return backingObject->language();
2952
2953     if ([attributeName isEqualToString:NSAccessibilityExpandedAttribute])
2954         return [NSNumber numberWithBool:backingObject->isExpanded()];
2955
2956     if ([attributeName isEqualToString:NSAccessibilityRequiredAttribute])
2957         return [NSNumber numberWithBool:backingObject->isRequired()];
2958
2959     if ([attributeName isEqualToString:NSAccessibilityInvalidAttribute])
2960         return backingObject->invalidStatus();
2961
2962     if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) {
2963         AccessibilityObject::AccessibilityChildrenVector ariaOwns;
2964         backingObject->ariaOwnsElements(ariaOwns);
2965         return convertToNSArray(ariaOwns);
2966     }
2967
2968     if ([attributeName isEqualToString:NSAccessibilityARIAPosInSetAttribute])
2969         return [NSNumber numberWithInt:backingObject->posInSet()];
2970     if ([attributeName isEqualToString:NSAccessibilityARIASetSizeAttribute])
2971         return [NSNumber numberWithInt:backingObject->setSize()];
2972
2973     if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2974         return [NSNumber numberWithBool:backingObject->isARIAGrabbed()];
2975
2976     if ([attributeName isEqualToString:NSAccessibilityDropEffectsAttribute]) {
2977         Vector<String> dropEffects = backingObject->determineARIADropEffects();
2978         return convertStringsToNSArray(dropEffects);
2979     }
2980
2981     if ([attributeName isEqualToString:NSAccessibilityPlaceholderValueAttribute])
2982         return backingObject->placeholderValue();
2983
2984     if ([attributeName isEqualToString:NSAccessibilityValueAutofillAvailableAttribute])
2985         return @(backingObject->isValueAutofillAvailable());
2986
2987     if ([attributeName isEqualToString:NSAccessibilityValueAutofillTypeAttribute]) {
2988         switch (backingObject->valueAutofillButtonType()) {
2989         case AutoFillButtonType::None:
2990             return @"none";
2991         case AutoFillButtonType::Credentials:
2992             return @"credentials";
2993         case AutoFillButtonType::Contacts:
2994             return @"contacts";
2995         case AutoFillButtonType::StrongPassword:
2996             return @"strong password";
2997         case AutoFillButtonType::CreditCard:
2998             return @"credit card";
2999         }
3000     }
3001
3002     if ([attributeName isEqualToString:NSAccessibilityValueAutofilledAttribute])
3003         return @(backingObject->isValueAutofilled());
3004
3005     if ([attributeName isEqualToString:NSAccessibilityHasPopupAttribute])
3006         return [NSNumber numberWithBool:backingObject->hasPopup()];
3007
3008     if ([attributeName isEqualToString:NSAccessibilityDatetimeValueAttribute])
3009         return backingObject->datetimeAttributeValue();
3010
3011     if ([attributeName isEqualToString:NSAccessibilityInlineTextAttribute])
3012         return @(backingObject->isInlineText());
3013
3014     // ARIA Live region attributes.
3015     if ([attributeName isEqualToString:NSAccessibilityARIALiveAttribute])
3016         return backingObject->liveRegionStatus();
3017     if ([attributeName isEqualToString:NSAccessibilityARIARelevantAttribute])
3018         return backingObject->liveRegionRelevant();
3019     if ([attributeName isEqualToString:NSAccessibilityARIAAtomicAttribute])
3020         return [NSNumber numberWithBool:backingObject->liveRegionAtomic()];
3021     if ([attributeName isEqualToString:NSAccessibilityElementBusyAttribute])
3022         return [NSNumber numberWithBool:backingObject->isBusy()];
3023
3024     // MathML Attributes.
3025     if (backingObject->isMathElement()) {
3026         if ([attributeName isEqualToString:NSAccessibilityMathRootIndexAttribute])
3027             return (backingObject->mathRootIndexObject()) ? backingObject->mathRootIndexObject()->wrapper() : 0;
3028         if ([attributeName isEqualToString:NSAccessibilityMathRootRadicandAttribute])
3029             return (backingObject->mathRadicandObject()) ? backingObject->mathRadicandObject()->wrapper() : 0;
3030         if ([attributeName isEqualToString:NSAccessibilityMathFractionNumeratorAttribute])
3031             return (backingObject->mathNumeratorObject()) ? backingObject->mathNumeratorObject()->wrapper() : 0;
3032         if ([attributeName isEqualToString:NSAccessibilityMathFractionDenominatorAttribute])
3033             return (backingObject->mathDenominatorObject()) ? backingObject->mathDenominatorObject()->wrapper() : 0;
3034         if ([attributeName isEqualToString:NSAccessibilityMathBaseAttribute])
3035             return (backingObject->mathBaseObject()) ? backingObject->mathBaseObject()->wrapper() : 0;
3036         if ([attributeName isEqualToString:NSAccessibilityMathSubscriptAttribute])
3037             return (backingObject->mathSubscriptObject()) ? backingObject->mathSubscriptObject()->wrapper() : 0;
3038         if ([attributeName isEqualToString:NSAccessibilityMathSuperscriptAttribute])
3039             return (backingObject->mathSuperscriptObject()) ? backingObject->mathSuperscriptObject()->wrapper() : 0;
3040         if ([attributeName isEqualToString:NSAccessibilityMathUnderAttribute])
3041             return (backingObject->mathUnderObject()) ? backingObject->mathUnderObject()->wrapper() : 0;
3042         if ([attributeName isEqualToString:NSAccessibilityMathOverAttribute])
3043             return (backingObject->mathOverObject()) ? backingObject->mathOverObject()->wrapper() : 0;
3044         if ([attributeName isEqualToString:NSAccessibilityMathFencedOpenAttribute])
3045             return backingObject->mathFencedOpenString();
3046         if ([attributeName isEqualToString:NSAccessibilityMathFencedCloseAttribute])
3047             return backingObject->mathFencedCloseString();
3048         if ([attributeName isEqualToString:NSAccessibilityMathLineThicknessAttribute])
3049             return [NSNumber numberWithInteger:backingObject->mathLineThickness()];
3050         if ([attributeName isEqualToString:NSAccessibilityMathPostscriptsAttribute])
3051             return [self accessibilityMathPostscriptPairs];
3052         if ([attributeName isEqualToString:NSAccessibilityMathPrescriptsAttribute])
3053             return [self accessibilityMathPrescriptPairs];
3054     }
3055
3056     if ([attributeName isEqualToString:NSAccessibilityExpandedTextValueAttribute])
3057         return backingObject->expandedTextValue();
3058
3059     if ([attributeName isEqualToString:NSAccessibilityDOMIdentifierAttribute])
3060         return backingObject->identifierAttribute();
3061     if ([attributeName isEqualToString:NSAccessibilityDOMClassListAttribute]) {
3062         Vector<String> classList;
3063         backingObject->classList(classList);
3064         return convertStringsToNSArray(classList);
3065     }
3066
3067     // This allows us to connect to a plugin that creates a shadow node for editing (like PDFs).
3068     if ([attributeName isEqualToString:@"_AXAssociatedPluginParent"])
3069         return [self associatedPluginParent];
3070
3071     // this is used only by DumpRenderTree for testing
3072     if ([attributeName isEqualToString:@"AXClickPoint"])
3073         return [NSValue valueWithPoint:backingObject->clickPoint()];
3074
3075     // This is used by DRT to verify CSS3 speech works.
3076     if ([attributeName isEqualToString:@"AXDRTSpeechAttribute"])
3077         return [self baseAccessibilitySpeechHint];
3078
3079     // Used by TestRunner and DRT AccessibilityController to find an accessible node by its element id.
3080     if ([attributeName isEqualToString:@"AXDRTElementIdAttribute"])
3081         return backingObject->identifierAttribute();
3082
3083     if ([attributeName isEqualToString:@"AXAutocompleteValue"])
3084         return backingObject->autoCompleteValue();
3085
3086     if ([attributeName isEqualToString:NSAccessibilityPopupValueAttribute])
3087         return backingObject->popupValue();
3088
3089     if ([attributeName isEqualToString:@"AXKeyShortcutsValue"])
3090         return backingObject->keyShortcutsValue();
3091
3092     if ([attributeName isEqualToString:@"AXARIAPressedIsPresent"])
3093         return [NSNumber numberWithBool:backingObject->pressedIsPresent()];
3094
3095     if ([attributeName isEqualToString:@"AXIsMultiline"])
3096         return [NSNumber numberWithBool:backingObject->ariaIsMultiline()];
3097
3098     if ([attributeName isEqualToString:@"AXReadOnlyValue"])
3099         return backingObject->readOnlyValue();
3100
3101     if ([attributeName isEqualToString:@"AXIsActiveDescendantOfFocusedContainer"])
3102         return [NSNumber numberWithBool:backingObject->isActiveDescendantOfFocusedContainer()];