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