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