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