fe6314da219e8f74f6f2cb462be526244de1c68b
[WebKit-https.git] / Source / WebCore / accessibility / mac / WebAccessibilityObjectWrapperMac.mm
1 /*
2  * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #import "config.h"
30 #import "WebAccessibilityObjectWrapperMac.h"
31
32 #if HAVE(ACCESSIBILITY)
33
34 #import "AXObjectCache.h"
35 #import "AccessibilityARIAGridRow.h"
36 #import "AccessibilityLabel.h"
37 #import "AccessibilityList.h"
38 #import "AccessibilityListBox.h"
39 #import "AccessibilityProgressIndicator.h"
40 #import "AccessibilityRenderObject.h"
41 #import "AccessibilityScrollView.h"
42 #import "AccessibilitySpinButton.h"
43 #import "AccessibilityTable.h"
44 #import "AccessibilityTableCell.h"
45 #import "AccessibilityTableColumn.h"
46 #import "AccessibilityTableRow.h"
47 #import "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 "FrameLoaderClient.h"
56 #import "FrameSelection.h"
57 #import "HTMLAnchorElement.h"
58 #import "HTMLAreaElement.h"
59 #import "HTMLFrameOwnerElement.h"
60 #import "HTMLImageElement.h"
61 #import "HTMLInputElement.h"
62 #import "HTMLNames.h"
63 #import "LocalizedStrings.h"
64 #import "MainFrame.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 "WebCoreObjCExtras.h"
80 #import <pal/spi/mac/HIServicesSPI.h>
81 #import <pal/spi/mac/NSAccessibilitySPI.h>
82 #import <wtf/ObjcRuntimeExtras.h>
83 #if ENABLE(TREE_DEBUGGING) || ENABLE(METER_ELEMENT)
84 #import <wtf/text/StringBuilder.h>
85 #endif
86
87 using namespace WebCore;
88 using namespace HTMLNames;
89
90 // Cell Tables
91 #ifndef NSAccessibilitySelectedCellsAttribute
92 #define NSAccessibilitySelectedCellsAttribute @"AXSelectedCells"
93 #endif
94
95 #ifndef NSAccessibilityVisibleCellsAttribute
96 #define NSAccessibilityVisibleCellsAttribute @"AXVisibleCells"
97 #endif
98
99 #ifndef NSAccessibilityRowIndexRangeAttribute
100 #define NSAccessibilityRowIndexRangeAttribute @"AXRowIndexRange"
101 #endif
102
103 #ifndef NSAccessibilityColumnIndexRangeAttribute
104 #define NSAccessibilityColumnIndexRangeAttribute @"AXColumnIndexRange"
105 #endif
106
107 #ifndef NSAccessibilityCellForColumnAndRowParameterizedAttribute
108 #define NSAccessibilityCellForColumnAndRowParameterizedAttribute @"AXCellForColumnAndRow"
109 #endif
110
111 #ifndef NSAccessibilityCellRole
112 #define NSAccessibilityCellRole @"AXCell"
113 #endif
114
115 // Lists
116 #ifndef NSAccessibilityContentListSubrole
117 #define NSAccessibilityContentListSubrole @"AXContentList"
118 #endif
119
120 #ifndef NSAccessibilityDefinitionListSubrole
121 #define NSAccessibilityDefinitionListSubrole @"AXDefinitionList"
122 #endif
123
124 #ifndef NSAccessibilityDescriptionListSubrole
125 #define NSAccessibilityDescriptionListSubrole @"AXDescriptionList"
126 #endif
127
128 #ifndef NSAccessibilityContentSeparatorSubrole
129 #define NSAccessibilityContentSeparatorSubrole @"AXContentSeparator"
130 #endif
131
132 #ifndef NSAccessibilityRubyBaseSubRole
133 #define NSAccessibilityRubyBaseSubrole @"AXRubyBase"
134 #endif
135
136 #ifndef NSAccessibilityRubyBlockSubrole
137 #define NSAccessibilityRubyBlockSubrole @"AXRubyBlock"
138 #endif
139
140 #ifndef NSAccessibilityRubyInlineSubrole
141 #define NSAccessibilityRubyInlineSubrole @"AXRubyInline"
142 #endif
143
144 #ifndef NSAccessibilityRubyRunSubrole
145 #define NSAccessibilityRubyRunSubrole @"AXRubyRun"
146 #endif
147
148 #ifndef NSAccessibilityRubyTextSubrole
149 #define NSAccessibilityRubyTextSubrole @"AXRubyText"
150 #endif
151
152 // Miscellaneous
153 #ifndef NSAccessibilityBlockQuoteLevelAttribute
154 #define NSAccessibilityBlockQuoteLevelAttribute @"AXBlockQuoteLevel"
155 #endif
156
157 #ifndef NSAccessibilityAccessKeyAttribute
158 #define NSAccessibilityAccessKeyAttribute @"AXAccessKey"
159 #endif
160
161 #ifndef NSAccessibilityValueAutofilledAttribute
162 #define NSAccessibilityValueAutofilledAttribute @"AXValueAutofilled"
163 #endif
164
165 #ifndef NSAccessibilityValueAutofillAvailableAttribute
166 #define NSAccessibilityValueAutofillAvailableAttribute @"AXValueAutofillAvailable"
167 #endif
168
169 #ifndef NSAccessibilityValueAutofillTypeAttribute
170 #define NSAccessibilityValueAutofillTypeAttribute @"AXValueAutofillType"
171 #endif
172
173 #ifndef NSAccessibilityLanguageAttribute
174 #define NSAccessibilityLanguageAttribute @"AXLanguage"
175 #endif
176
177 #ifndef NSAccessibilityRequiredAttribute
178 #define NSAccessibilityRequiredAttribute @"AXRequired"
179 #endif
180
181 #ifndef NSAccessibilityInvalidAttribute
182 #define NSAccessibilityInvalidAttribute @"AXInvalid"
183 #endif
184
185 #ifndef NSAccessibilityOwnsAttribute
186 #define NSAccessibilityOwnsAttribute @"AXOwns"
187 #endif
188
189 #ifndef NSAccessibilityGrabbedAttribute
190 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
191 #endif
192
193 #ifndef NSAccessibilityDatetimeValueAttribute
194 #define NSAccessibilityDatetimeValueAttribute @"AXDateTimeValue"
195 #endif
196
197 #ifndef NSAccessibilityInlineTextAttribute
198 #define NSAccessibilityInlineTextAttribute @"AXInlineText"
199 #endif
200
201 #ifndef NSAccessibilityDropEffectsAttribute
202 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
203 #endif
204
205 #ifndef NSAccessibilityARIALiveAttribute
206 #define NSAccessibilityARIALiveAttribute @"AXARIALive"
207 #endif
208
209 #ifndef NSAccessibilityARIAAtomicAttribute
210 #define NSAccessibilityARIAAtomicAttribute @"AXARIAAtomic"
211 #endif
212
213 #ifndef NSAccessibilityARIARelevantAttribute
214 #define NSAccessibilityARIARelevantAttribute @"AXARIARelevant"
215 #endif
216
217 #ifndef NSAccessibilityElementBusyAttribute
218 #define NSAccessibilityElementBusyAttribute @"AXElementBusy"
219 #endif
220
221 #ifndef NSAccessibilityARIAPosInSetAttribute
222 #define NSAccessibilityARIAPosInSetAttribute @"AXARIAPosInSet"
223 #endif
224
225 #ifndef NSAccessibilityARIASetSizeAttribute
226 #define NSAccessibilityARIASetSizeAttribute @"AXARIASetSize"
227 #endif
228
229 #ifndef NSAccessibilityLoadingProgressAttribute
230 #define NSAccessibilityLoadingProgressAttribute @"AXLoadingProgress"
231 #endif
232
233 #ifndef NSAccessibilityHasPopupAttribute
234 #define NSAccessibilityHasPopupAttribute @"AXHasPopup"
235 #endif
236
237 #ifndef NSAccessibilityPlaceholderValueAttribute
238 #define NSAccessibilityPlaceholderValueAttribute @"AXPlaceholderValue"
239 #endif
240
241 #define NSAccessibilityTextMarkerIsValidParameterizedAttribute @"AXTextMarkerIsValid"
242 #define NSAccessibilityIndexForTextMarkerParameterizedAttribute @"AXIndexForTextMarker"
243 #define NSAccessibilityTextMarkerForIndexParameterizedAttribute @"AXTextMarkerForIndex"
244
245 #ifndef NSAccessibilityScrollToVisibleAction
246 #define NSAccessibilityScrollToVisibleAction @"AXScrollToVisible"
247 #endif
248
249 #ifndef NSAccessibilityPathAttribute
250 #define NSAccessibilityPathAttribute @"AXPath"
251 #endif
252
253 #ifndef NSAccessibilityExpandedTextValueAttribute
254 #define NSAccessibilityExpandedTextValueAttribute @"AXExpandedTextValue"
255 #endif
256
257 #ifndef NSAccessibilityIsMultiSelectableAttribute
258 #define NSAccessibilityIsMultiSelectableAttribute @"AXIsMultiSelectable"
259 #endif
260
261 #ifndef NSAccessibilityDocumentURIAttribute
262 #define NSAccessibilityDocumentURIAttribute @"AXDocumentURI"
263 #endif
264
265 #ifndef NSAccessibilityDocumentEncodingAttribute
266 #define NSAccessibilityDocumentEncodingAttribute @"AXDocumentEncoding"
267 #endif
268
269 #ifndef NSAccessibilityAriaControlsAttribute
270 #define NSAccessibilityAriaControlsAttribute @"AXARIAControls"
271 #endif
272
273 #define NSAccessibilityDOMIdentifierAttribute @"AXDOMIdentifier"
274 #define NSAccessibilityDOMClassListAttribute @"AXDOMClassList"
275
276 #ifndef NSAccessibilityARIACurrentAttribute
277 #define NSAccessibilityARIACurrentAttribute @"AXARIACurrent"
278 #endif
279
280 // Table/grid attributes
281 #ifndef NSAccessibilityARIAColumnIndexAttribute
282 #define NSAccessibilityARIAColumnIndexAttribute @"AXARIAColumnIndex"
283 #endif
284
285 #ifndef NSAccessibilityARIARowIndexAttribute
286 #define NSAccessibilityARIARowIndexAttribute @"AXARIARowIndex"
287 #endif
288
289 #ifndef NSAccessibilityARIAColumnCountAttribute
290 #define NSAccessibilityARIAColumnCountAttribute @"AXARIAColumnCount"
291 #endif
292
293 #ifndef NSAccessibilityARIARowCountAttribute
294 #define NSAccessibilityARIARowCountAttribute @"AXARIARowCount"
295 #endif
296
297
298 #ifndef NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute
299 #define NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute @"AXUIElementCountForSearchPredicate"
300 #endif
301
302 #ifndef NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute
303 #define NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute @"AXUIElementsForSearchPredicate"
304 #endif
305
306 // Text markers
307 #ifndef NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute
308 #define NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute @"AXEndTextMarkerForBounds"
309 #endif
310
311 #ifndef NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute
312 #define NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute @"AXStartTextMarkerForBounds"
313 #endif
314
315 #ifndef NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute
316 #define NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute @"AXLineTextMarkerRangeForTextMarker"
317 #endif
318
319 // Text selection
320 #ifndef NSAccessibilitySelectTextActivity
321 #define NSAccessibilitySelectTextActivity @"AXSelectTextActivity"
322 #endif
323
324 #ifndef NSAccessibilitySelectTextActivityFindAndReplace
325 #define NSAccessibilitySelectTextActivityFindAndReplace @"AXSelectTextActivityFindAndReplace"
326 #endif
327
328 #ifndef NSAccessibilitySelectTextActivityFindAndSelect
329 #define NSAccessibilitySelectTextActivityFindAndSelect @"AXSelectTextActivityFindAndSelect"
330 #endif
331
332 #ifndef kAXSelectTextActivityFindAndCapitalize
333 #define kAXSelectTextActivityFindAndCapitalize @"AXSelectTextActivityFindAndCapitalize"
334 #endif
335
336 #ifndef kAXSelectTextActivityFindAndLowercase
337 #define kAXSelectTextActivityFindAndLowercase @"AXSelectTextActivityFindAndLowercase"
338 #endif
339
340 #ifndef kAXSelectTextActivityFindAndUppercase
341 #define kAXSelectTextActivityFindAndUppercase @"AXSelectTextActivityFindAndUppercase"
342 #endif
343
344 #ifndef NSAccessibilitySelectTextAmbiguityResolution
345 #define NSAccessibilitySelectTextAmbiguityResolution @"AXSelectTextAmbiguityResolution"
346 #endif
347
348 #ifndef NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection
349 #define NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection @"AXSelectTextAmbiguityResolutionClosestAfterSelection"
350 #endif
351
352 #ifndef NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection
353 #define NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection @"AXSelectTextAmbiguityResolutionClosestBeforeSelection"
354 #endif
355
356 #ifndef NSAccessibilitySelectTextAmbiguityResolutionClosestToSelection
357 #define NSAccessibilitySelectTextAmbiguityResolutionClosestToSelection @"AXSelectTextAmbiguityResolutionClosestToSelection"
358 #endif
359
360 #ifndef NSAccessibilitySelectTextReplacementString
361 #define NSAccessibilitySelectTextReplacementString @"AXSelectTextReplacementString"
362 #endif
363
364 #ifndef NSAccessibilitySelectTextSearchStrings
365 #define NSAccessibilitySelectTextSearchStrings @"AXSelectTextSearchStrings"
366 #endif
367
368 #ifndef NSAccessibilitySelectTextWithCriteriaParameterizedAttribute
369 #define NSAccessibilitySelectTextWithCriteriaParameterizedAttribute @"AXSelectTextWithCriteria"
370 #endif
371
372 // Math attributes
373 #define NSAccessibilityMathRootRadicandAttribute @"AXMathRootRadicand"
374 #define NSAccessibilityMathRootIndexAttribute @"AXMathRootIndex"
375 #define NSAccessibilityMathFractionDenominatorAttribute @"AXMathFractionDenominator"
376 #define NSAccessibilityMathFractionNumeratorAttribute @"AXMathFractionNumerator"
377 #define NSAccessibilityMathBaseAttribute @"AXMathBase"
378 #define NSAccessibilityMathSubscriptAttribute @"AXMathSubscript"
379 #define NSAccessibilityMathSuperscriptAttribute @"AXMathSuperscript"
380 #define NSAccessibilityMathUnderAttribute @"AXMathUnder"
381 #define NSAccessibilityMathOverAttribute @"AXMathOver"
382 #define NSAccessibilityMathFencedOpenAttribute @"AXMathFencedOpen"
383 #define NSAccessibilityMathFencedCloseAttribute @"AXMathFencedClose"
384 #define NSAccessibilityMathLineThicknessAttribute @"AXMathLineThickness"
385 #define NSAccessibilityMathPrescriptsAttribute @"AXMathPrescripts"
386 #define NSAccessibilityMathPostscriptsAttribute @"AXMathPostscripts"
387
388 #ifndef NSAccessibilityPreventKeyboardDOMEventDispatchAttribute
389 #define NSAccessibilityPreventKeyboardDOMEventDispatchAttribute @"AXPreventKeyboardDOMEventDispatch"
390 #endif
391
392 #ifndef NSAccessibilityCaretBrowsingEnabledAttribute
393 #define NSAccessibilityCaretBrowsingEnabledAttribute @"AXCaretBrowsingEnabled"
394 #endif
395
396 #ifndef NSAccessibilitFocusableAncestorAttribute
397 #define NSAccessibilityFocusableAncestorAttribute @"AXFocusableAncestor"
398 #endif
399
400 #ifndef NSAccessibilityEditableAncestorAttribute
401 #define NSAccessibilityEditableAncestorAttribute @"AXEditableAncestor"
402 #endif
403
404 #ifndef NSAccessibilityHighestEditableAncestorAttribute
405 #define NSAccessibilityHighestEditableAncestorAttribute @"AXHighestEditableAncestor"
406 #endif
407
408 extern "C" AXUIElementRef NSAccessibilityCreateAXUIElementRef(id element);
409
410 @implementation WebAccessibilityObjectWrapper
411
412 - (void)unregisterUniqueIdForUIElement
413 {
414     NSAccessibilityUnregisterUniqueIdForUIElement(self);
415 }
416
417 - (void)detach
418 {
419     // Send unregisterUniqueIdForUIElement unconditionally because if it is
420     // ever accidentally not done (via other bugs in our AX implementation) you
421     // end up with a crash like <rdar://problem/4273149>.  It is safe and not
422     // expensive to send even if the object is not registered.
423     [self unregisterUniqueIdForUIElement];
424     [super detach];
425 }
426
427 - (id)attachmentView
428 {
429     ASSERT(m_object->isAttachment());
430     Widget* widget = m_object->widgetForAttachmentView();
431     if (!widget)
432         return nil;
433     return NSAccessibilityUnignoredDescendant(widget->platformWidget());
434 }
435
436 #pragma mark SystemInterface wrappers
437
438 static inline BOOL AXObjectIsTextMarker(id obj)
439 {
440     return obj != nil && CFGetTypeID(obj) == AXTextMarkerGetTypeID();
441 }
442
443 static inline BOOL AXObjectIsTextMarkerRange(id obj)
444 {
445     return obj != nil && CFGetTypeID(obj) == AXTextMarkerRangeGetTypeID();
446 }
447
448 static id AXTextMarkerRange(id startMarker, id endMarker)
449 {
450     ASSERT(startMarker != nil);
451     ASSERT(endMarker != nil);
452     ASSERT(CFGetTypeID(startMarker) == AXTextMarkerGetTypeID());
453     ASSERT(CFGetTypeID(endMarker) == AXTextMarkerGetTypeID());
454     return CFBridgingRelease(AXTextMarkerRangeCreate(kCFAllocatorDefault, (AXTextMarkerRef)startMarker, (AXTextMarkerRef)endMarker));
455 }
456
457 static id AXTextMarkerRangeStart(id range)
458 {
459     ASSERT(range != nil);
460     ASSERT(CFGetTypeID(range) == AXTextMarkerRangeGetTypeID());
461     return CFBridgingRelease(AXTextMarkerRangeCopyStartMarker((AXTextMarkerRangeRef)range));
462 }
463
464 static id AXTextMarkerRangeEnd(id range)
465 {
466     ASSERT(range != nil);
467     ASSERT(CFGetTypeID(range) == AXTextMarkerRangeGetTypeID());
468     return CFBridgingRelease(AXTextMarkerRangeCopyEndMarker((AXTextMarkerRangeRef)range));
469 }
470
471 #pragma mark Other helpers
472
473 - (IntRect)screenToContents:(const IntRect&)rect
474 {
475     Document* document = m_object->document();
476     if (!document)
477         return IntRect();
478     
479     FrameView* frameView = document->view();
480     if (!frameView)
481         return IntRect();
482     
483     IntPoint startPoint = frameView->screenToContents(rect.minXMaxYCorner());
484     IntPoint endPoint = frameView->screenToContents(rect.maxXMinYCorner());
485     return IntRect(startPoint.x(), startPoint.y(), endPoint.x() - startPoint.x(), endPoint.y() - startPoint.y());
486 }
487
488 #pragma mark Select text helpers
489
490 static AccessibilitySelectTextCriteria accessibilitySelectTextCriteriaForCriteriaParameterizedAttribute(const NSDictionary *parameterizedAttribute)
491 {
492     NSString *activityParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextActivity];
493     NSString *ambiguityResolutionParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextAmbiguityResolution];
494     NSString *replacementStringParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextReplacementString];
495     NSArray *searchStringsParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextSearchStrings];
496     
497     AccessibilitySelectTextActivity activity = FindAndSelectActivity;
498     if ([activityParameter isKindOfClass:[NSString class]]) {
499         if ([activityParameter isEqualToString:NSAccessibilitySelectTextActivityFindAndReplace])
500             activity = FindAndReplaceActivity;
501         else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndCapitalize])
502             activity = FindAndCapitalize;
503         else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndLowercase])
504             activity = FindAndLowercase;
505         else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndUppercase])
506             activity = FindAndUppercase;
507     }
508     
509     AccessibilitySelectTextAmbiguityResolution ambiguityResolution = ClosestToSelectionAmbiguityResolution;
510     if ([ambiguityResolutionParameter isKindOfClass:[NSString class]]) {
511         if ([ambiguityResolutionParameter isEqualToString:NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection])
512             ambiguityResolution = ClosestAfterSelectionAmbiguityResolution;
513         else if ([ambiguityResolutionParameter isEqualToString:NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection])
514             ambiguityResolution = ClosestBeforeSelectionAmbiguityResolution;
515     }
516     
517     String replacementString;
518     if ([replacementStringParameter isKindOfClass:[NSString class]])
519         replacementString = replacementStringParameter;
520     
521     AccessibilitySelectTextCriteria criteria(activity, ambiguityResolution, replacementString);
522     
523     if ([searchStringsParameter isKindOfClass:[NSArray class]]) {
524         size_t searchStringsCount = static_cast<size_t>([searchStringsParameter count]);
525         criteria.searchStrings.reserveInitialCapacity(searchStringsCount);
526         for (NSString *searchString in searchStringsParameter) {
527             if ([searchString isKindOfClass:[NSString class]])
528                 criteria.searchStrings.uncheckedAppend(searchString);
529         }
530     }
531     
532     return criteria;
533 }
534
535 #pragma mark Text Marker helpers
536
537 static BOOL getBytesFromAXTextMarker(CFTypeRef textMarker, void* bytes, size_t length)
538 {
539     if (!textMarker)
540         return NO;
541
542     AXTextMarkerRef ref = (AXTextMarkerRef)textMarker;
543     ASSERT(CFGetTypeID(ref) == AXTextMarkerGetTypeID());
544     if (CFGetTypeID(ref) != AXTextMarkerGetTypeID())
545         return NO;
546
547     CFIndex expectedLength = length;
548     if (AXTextMarkerGetLength(ref) != expectedLength)
549         return NO;
550
551     memcpy(bytes, AXTextMarkerGetBytePtr(ref), length);
552     return YES;
553 }
554
555 static bool isTextMarkerIgnored(id textMarker)
556 {
557     if (!textMarker)
558         return false;
559     
560     TextMarkerData textMarkerData;
561     if (!getBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))
562         return false;
563     
564     return textMarkerData.ignored;
565 }
566
567 - (AccessibilityObject*)accessibilityObjectForTextMarker:(id)textMarker
568 {
569     return accessibilityObjectForTextMarker(m_object->axObjectCache(), textMarker);
570 }
571
572 static AccessibilityObject* accessibilityObjectForTextMarker(AXObjectCache* cache, id textMarker)
573 {
574     if (!textMarker || !cache || isTextMarkerIgnored(textMarker))
575         return nullptr;
576     
577     TextMarkerData textMarkerData;
578     if (!getBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))
579         return nullptr;
580     return cache->accessibilityObjectForTextMarkerData(textMarkerData);
581 }
582
583 - (id)textMarkerRangeFromRange:(const RefPtr<Range>)range
584 {
585     return textMarkerRangeFromRange(m_object->axObjectCache(), range);
586 }
587
588 static id textMarkerRangeFromRange(AXObjectCache* cache, const RefPtr<Range> range)
589 {
590     id startTextMarker = startOrEndTextmarkerForRange(cache, range, true);
591     id endTextMarker = startOrEndTextmarkerForRange(cache, range, false);
592     return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);
593 }
594
595 - (id)startOrEndTextMarkerForRange:(const RefPtr<Range>)range isStart:(BOOL)isStart
596 {
597     return startOrEndTextmarkerForRange(m_object->axObjectCache(), range, isStart);
598 }
599
600 static id startOrEndTextmarkerForRange(AXObjectCache* cache, RefPtr<Range> range, bool isStart)
601 {
602     if (!cache)
603         return nil;
604     
605     TextMarkerData textMarkerData;
606     cache->startOrEndTextMarkerDataForRange(textMarkerData, range, isStart);
607     if (!textMarkerData.axID)
608         return nil;
609     
610     return CFBridgingRelease(AXTextMarkerCreate(kCFAllocatorDefault, (const UInt8*)&textMarkerData, sizeof(textMarkerData)));
611 }
612
613 static id nextTextMarkerForCharacterOffset(AXObjectCache* cache, CharacterOffset& characterOffset)
614 {
615     if (!cache)
616         return nil;
617     
618     TextMarkerData textMarkerData;
619     cache->textMarkerDataForNextCharacterOffset(textMarkerData, characterOffset);
620     if (!textMarkerData.axID)
621         return nil;
622     return CFBridgingRelease(AXTextMarkerCreate(kCFAllocatorDefault, (const UInt8*)&textMarkerData, sizeof(textMarkerData)));
623 }
624
625 static id previousTextMarkerForCharacterOffset(AXObjectCache* cache, CharacterOffset& characterOffset)
626 {
627     if (!cache)
628         return nil;
629     
630     TextMarkerData textMarkerData;
631     cache->textMarkerDataForPreviousCharacterOffset(textMarkerData, characterOffset);
632     if (!textMarkerData.axID)
633         return nil;
634     return CFBridgingRelease(AXTextMarkerCreate(kCFAllocatorDefault, (const UInt8*)&textMarkerData, sizeof(textMarkerData)));
635 }
636
637 - (id)nextTextMarkerForCharacterOffset:(CharacterOffset&)characterOffset
638 {
639     return nextTextMarkerForCharacterOffset(m_object->axObjectCache(), characterOffset);
640 }
641
642 - (id)previousTextMarkerForCharacterOffset:(CharacterOffset&)characterOffset
643 {
644     return previousTextMarkerForCharacterOffset(m_object->axObjectCache(), characterOffset);
645 }
646
647 - (id)textMarkerForCharacterOffset:(CharacterOffset&)characterOffset
648 {
649     return textMarkerForCharacterOffset(m_object->axObjectCache(), characterOffset);
650 }
651
652 static id textMarkerForCharacterOffset(AXObjectCache* cache, const CharacterOffset& characterOffset)
653 {
654     if (!cache)
655         return nil;
656     
657     TextMarkerData textMarkerData;
658     cache->textMarkerDataForCharacterOffset(textMarkerData, characterOffset);
659     if (!textMarkerData.axID && !textMarkerData.ignored)
660         return nil;
661     
662     return CFBridgingRelease(AXTextMarkerCreate(kCFAllocatorDefault, (const UInt8*)&textMarkerData, sizeof(textMarkerData)));
663 }
664
665 - (RefPtr<Range>)rangeForTextMarkerRange:(id)textMarkerRange
666 {
667     if (!textMarkerRange)
668         return nullptr;
669     
670     id startTextMarker = AXTextMarkerRangeStart(textMarkerRange);
671     id endTextMarker = AXTextMarkerRangeEnd(textMarkerRange);
672     
673     if (!startTextMarker || !endTextMarker)
674         return nullptr;
675     
676     AXObjectCache* cache = m_object->axObjectCache();
677     if (!cache)
678         return nullptr;
679     
680     CharacterOffset startCharacterOffset = [self characterOffsetForTextMarker:startTextMarker];
681     CharacterOffset endCharacterOffset = [self characterOffsetForTextMarker:endTextMarker];
682     return cache->rangeForUnorderedCharacterOffsets(startCharacterOffset, endCharacterOffset);
683 }
684
685 static CharacterOffset characterOffsetForTextMarker(AXObjectCache* cache, CFTypeRef textMarker)
686 {
687     if (!cache || !textMarker)
688         return CharacterOffset();
689     
690     TextMarkerData textMarkerData;
691     if (!getBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))
692         return CharacterOffset();
693     
694     return cache->characterOffsetForTextMarkerData(textMarkerData);
695 }
696
697 - (CharacterOffset)characterOffsetForTextMarker:(id)textMarker
698 {
699     return characterOffsetForTextMarker(m_object->axObjectCache(), textMarker);
700 }
701
702 static id textMarkerForVisiblePosition(AXObjectCache* cache, const VisiblePosition& visiblePos)
703 {
704     ASSERT(cache);
705
706     auto textMarkerData = cache->textMarkerDataForVisiblePosition(visiblePos);
707     if (!textMarkerData)
708         return nil;
709
710     return CFBridgingRelease(AXTextMarkerCreate(kCFAllocatorDefault, (const UInt8*)&textMarkerData.value(), sizeof(textMarkerData.value())));
711 }
712
713 - (id)textMarkerForVisiblePosition:(const VisiblePosition &)visiblePos
714 {
715     return textMarkerForVisiblePosition(m_object->axObjectCache(), visiblePos);
716 }
717
718 - (id)textMarkerForFirstPositionInTextControl:(HTMLTextFormControlElement &)textControl
719 {
720     auto *cache = m_object->axObjectCache();
721     if (!cache)
722         return nil;
723
724     auto textMarkerData = cache->textMarkerDataForFirstPositionInTextControl(textControl);
725     if (!textMarkerData)
726         return nil;
727
728     return CFBridgingRelease(AXTextMarkerCreate(kCFAllocatorDefault, (const UInt8*)&textMarkerData.value(), sizeof(textMarkerData.value())));
729 }
730
731 static VisiblePosition visiblePositionForTextMarker(AXObjectCache* cache, CFTypeRef textMarker)
732 {
733     ASSERT(cache);
734     
735     if (!textMarker)
736         return VisiblePosition();
737     TextMarkerData textMarkerData;
738     if (!getBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))
739         return VisiblePosition();
740     
741     return cache->visiblePositionForTextMarkerData(textMarkerData);
742 }
743
744 - (VisiblePosition)visiblePositionForTextMarker:(id)textMarker
745 {
746     return visiblePositionForTextMarker(m_object->axObjectCache(), textMarker);
747 }
748
749 static VisiblePosition visiblePositionForStartOfTextMarkerRange(AXObjectCache* cache, id textMarkerRange)
750 {
751     return visiblePositionForTextMarker(cache, AXTextMarkerRangeStart(textMarkerRange));
752 }
753
754 static VisiblePosition visiblePositionForEndOfTextMarkerRange(AXObjectCache* cache, id textMarkerRange)
755 {
756     return visiblePositionForTextMarker(cache, AXTextMarkerRangeEnd(textMarkerRange));
757 }
758
759 static id textMarkerRangeFromMarkers(id textMarker1, id textMarker2)
760 {
761     if (!textMarker1 || !textMarker2)
762         return nil;
763     
764     return AXTextMarkerRange(textMarker1, textMarker2);
765 }
766
767 // When modifying attributed strings, the range can come from a source which may provide faulty information (e.g. the spell checker).
768 // To protect against such cases the range should be validated before adding or removing attributes.
769 static BOOL AXAttributedStringRangeIsValid(NSAttributedString *attrString, NSRange range)
770 {
771     return (range.location < [attrString length] && NSMaxRange(range) <= [attrString length]);
772 }
773
774 static void AXAttributeStringSetFont(NSMutableAttributedString *attrString, NSString *attribute, CTFontRef font, NSRange range)
775 {
776     if (!AXAttributedStringRangeIsValid(attrString, range))
777         return;
778
779     if (font) {
780         NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
781             static_cast<NSString *>(adoptCF(CTFontCopyPostScriptName(font)).get()), NSAccessibilityFontNameKey,
782             static_cast<NSString *>(adoptCF(CTFontCopyFamilyName(font)).get()), NSAccessibilityFontFamilyKey,
783             static_cast<NSString *>(adoptCF(CTFontCopyDisplayName(font)).get()), NSAccessibilityVisibleNameKey,
784             [NSNumber numberWithFloat:CTFontGetSize(font)], NSAccessibilityFontSizeKey,
785             nil];
786         
787         [attrString addAttribute:attribute value:dict range:range];
788     } else
789         [attrString removeAttribute:attribute range:range];
790     
791 }
792
793 static CGColorRef CreateCGColorIfDifferent(NSColor *nsColor, CGColorRef existingColor)
794 {
795     // get color information assuming NSDeviceRGBColorSpace
796     NSColor *rgbColor = [nsColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
797     if (rgbColor == nil)
798         rgbColor = [NSColor blackColor];
799     CGFloat components[4];
800     [rgbColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
801     
802     // create a new CGColorRef to return
803     CGColorSpaceRef cgColorSpace = CGColorSpaceCreateDeviceRGB();
804     CGColorRef cgColor = CGColorCreate(cgColorSpace, components);
805     CGColorSpaceRelease(cgColorSpace);
806     
807     // check for match with existing color
808     if (existingColor && CGColorEqualToColor(cgColor, existingColor)) {
809         CGColorRelease(cgColor);
810         cgColor = nullptr;
811     }
812     
813     return cgColor;
814 }
815
816 static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range)
817 {
818     if (!AXAttributedStringRangeIsValid(attrString, range))
819         return;
820     
821     if (color) {
822         CGColorRef existingColor = (CGColorRef) [attrString attribute:attribute atIndex:range.location effectiveRange:nil];
823         CGColorRef cgColor = CreateCGColorIfDifferent(color, existingColor);
824         if (cgColor) {
825             [attrString addAttribute:attribute value:(id)cgColor range:range];
826             CGColorRelease(cgColor);
827         }
828     } else
829         [attrString removeAttribute:attribute range:range];
830 }
831
832 static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range)
833 {
834     if (!AXAttributedStringRangeIsValid(attrString, range))
835         return;
836     
837     if (number)
838         [attrString addAttribute:attribute value:number range:range];
839     else
840         [attrString removeAttribute:attribute range:range];
841 }
842
843 static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
844 {
845     const RenderStyle& style = renderer->style();
846     
847     // set basic font info
848     AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style.fontCascade().primaryFont().getCTFont(), range);
849     
850     // set basic colors
851     AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style.visitedDependentColor(CSSPropertyColor)), range);
852     AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style.visitedDependentColor(CSSPropertyBackgroundColor)), range);
853     
854     // set super/sub scripting
855     EVerticalAlign alignment = style.verticalAlign();
856     if (alignment == SUB)
857         AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:(-1)], range);
858     else if (alignment == SUPER)
859         AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:1], range);
860     else
861         [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range];
862     
863     // set shadow
864     if (style.textShadow())
865         AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, @YES, range);
866     else
867         [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range];
868     
869     // set underline and strikethrough
870     int decor = style.textDecorationsInEffect();
871     if ((decor & TextDecorationUnderline) == 0) {
872         [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range];
873         [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range];
874     }
875     
876     if ((decor & TextDecorationLineThrough) == 0) {
877         [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range];
878         [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range];
879     }
880     
881     if ((decor & (TextDecorationUnderline | TextDecorationLineThrough)) != 0) {
882         // FIXME: Should the underline style be reported here?
883         auto decorationStyles = TextDecorationPainter::stylesForRenderer(*renderer, decor);
884
885         if ((decor & TextDecorationUnderline) != 0) {
886             AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, @YES, range);
887             AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(decorationStyles.underlineColor), range);
888         }
889         
890         if ((decor & TextDecorationLineThrough) != 0) {
891             AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, @YES, range);
892             AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(decorationStyles.linethroughColor), range);
893         }
894     }
895     
896     // Indicate background highlighting.
897     for (Node* node = renderer->node(); node; node = node->parentNode()) {
898         if (node->hasTagName(markTag))
899             AXAttributeStringSetNumber(attrString, @"AXHighlight", @YES, range);
900     }
901 }
902
903 static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
904 {
905     if (!AXAttributedStringRangeIsValid(attrString, range))
906         return;
907     
908     AccessibilityObject* obj = renderer->document().axObjectCache()->getOrCreate(renderer);
909     int quoteLevel = obj->blockquoteLevel();
910     
911     if (quoteLevel)
912         [attrString addAttribute:NSAccessibilityBlockQuoteLevelAttribute value:[NSNumber numberWithInt:quoteLevel] range:range];
913     else
914         [attrString removeAttribute:NSAccessibilityBlockQuoteLevelAttribute range:range];
915 }
916
917 static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, StringView text, NSRange range)
918 {
919     if (unifiedTextCheckerEnabled(node->document().frame())) {
920         // Check the spelling directly since document->markersForNode() does not store the misspelled marking when the cursor is in a word.
921         TextCheckerClient* checker = node->document().frame()->editor().textChecker();
922         
923         // checkTextOfParagraph is the only spelling/grammar checker implemented in WK1 and WK2
924         Vector<TextCheckingResult> results;
925         checkTextOfParagraph(*checker, text, TextCheckingTypeSpelling, results, node->document().frame()->selection().selection());
926         
927         size_t size = results.size();
928         for (unsigned i = 0; i < size; i++) {
929             const TextCheckingResult& result = results[i];
930             AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, @YES, NSMakeRange(result.location + range.location, result.length));
931 #if PLATFORM(MAC)
932             AXAttributeStringSetNumber(attrString, NSAccessibilityMarkedMisspelledTextAttribute, @YES, NSMakeRange(result.location + range.location, result.length));
933 #endif
934         }
935         return;
936     }
937
938     for (unsigned currentPosition = 0; currentPosition < text.length(); ) {
939         int misspellingLocation = -1;
940         int misspellingLength = 0;
941         node->document().frame()->editor().textChecker()->checkSpellingOfString(text.substring(currentPosition), &misspellingLocation, &misspellingLength);
942         if (misspellingLocation == -1 || !misspellingLength)
943             break;
944         
945         NSRange spellRange = NSMakeRange(range.location + currentPosition + misspellingLocation, misspellingLength);
946         AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, @YES, spellRange);
947 #if PLATFORM(MAC)
948         AXAttributeStringSetNumber(attrString, NSAccessibilityMarkedMisspelledTextAttribute, @YES, spellRange);
949 #endif
950
951         currentPosition += misspellingLocation + misspellingLength;
952     }
953 }
954
955 static void AXAttributeStringSetExpandedTextValue(NSMutableAttributedString *attrString, RenderObject* renderer, NSRange range)
956 {
957     if (!renderer || !AXAttributedStringRangeIsValid(attrString, range))
958         return;
959     AccessibilityObject* axObject = renderer->document().axObjectCache()->getOrCreate(renderer);
960     if (axObject->supportsExpandedTextValue())
961         [attrString addAttribute:NSAccessibilityExpandedTextValueAttribute value:axObject->expandedTextValue() range:range];
962     else
963         [attrString removeAttribute:NSAccessibilityExpandedTextValueAttribute range:range];
964 }
965
966 static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
967 {
968     if (!renderer)
969         return;
970     
971     if (!AXAttributedStringRangeIsValid(attrString, range))
972         return;
973     
974     // Sometimes there are objects between the text and the heading.
975     // In those cases the parent hierarchy should be queried to see if there is a heading level.
976     int parentHeadingLevel = 0;
977     AccessibilityObject* parentObject = renderer->document().axObjectCache()->getOrCreate(renderer->parent());
978     for (; parentObject; parentObject = parentObject->parentObject()) {
979         parentHeadingLevel = parentObject->headingLevel();
980         if (parentHeadingLevel)
981             break;
982     }
983     
984     if (parentHeadingLevel)
985         [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range];
986     else
987         [attrString removeAttribute:@"AXHeadingLevel" range:range];
988 }
989
990 static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range)
991 {
992     if (!AXAttributedStringRangeIsValid(attrString, range))
993         return;
994     
995     if (is<AccessibilityRenderObject>(object)) {
996         // make a serializable AX object
997         
998         RenderObject* renderer = downcast<AccessibilityRenderObject>(*object).renderer();
999         if (!renderer)
1000             return;
1001         
1002         AXObjectCache* cache = renderer->document().axObjectCache();
1003         if (!cache)
1004             return;
1005         
1006         AXUIElementRef axElement = NSAccessibilityCreateAXUIElementRef(object->wrapper());
1007         if (axElement) {
1008             [attrString addAttribute:attribute value:(id)axElement range:range];
1009             CFRelease(axElement);
1010         }
1011     } else
1012         [attrString removeAttribute:attribute range:range];
1013 }
1014
1015 static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, StringView text)
1016 {
1017     // skip invisible text
1018     RenderObject* renderer = node->renderer();
1019     if (!renderer)
1020         return;
1021     
1022     // easier to calculate the range before appending the string
1023     NSRange attrStringRange = NSMakeRange([attrString length], text.length());
1024     
1025     // append the string from this node
1026     [[attrString mutableString] appendString:text.createNSStringWithoutCopying().get()];
1027     
1028     // add new attributes and remove irrelevant inherited ones
1029     // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge
1030     // identical colors.  Workaround is to not replace an existing color attribute if it matches what we are adding.  This also means
1031     // we cannot just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually.
1032     
1033     // remove inherited attachment from prior AXAttributedStringAppendReplaced
1034     [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange];
1035 #if PLATFORM(MAC)
1036     [attrString removeAttribute:NSAccessibilityMarkedMisspelledTextAttribute range:attrStringRange];
1037 #endif
1038     [attrString removeAttribute:NSAccessibilityMisspelledTextAttribute range:attrStringRange];
1039     
1040     // set new attributes
1041     AXAttributeStringSetStyle(attrString, renderer, attrStringRange);
1042     AXAttributeStringSetHeadingLevel(attrString, renderer, attrStringRange);
1043     AXAttributeStringSetBlockquoteLevel(attrString, renderer, attrStringRange);
1044     AXAttributeStringSetExpandedTextValue(attrString, renderer, attrStringRange);
1045     AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AccessibilityObject::anchorElementForNode(node), attrStringRange);
1046     
1047     // do spelling last because it tends to break up the range
1048     AXAttributeStringSetSpelling(attrString, node, text, attrStringRange);
1049 }
1050
1051 static NSString* nsStringForReplacedNode(Node* replacedNode)
1052 {
1053     // we should always be given a rendered node and a replaced node, but be safe
1054     // replaced nodes are either attachments (widgets) or images
1055     if (!replacedNode || !isRendererReplacedElement(replacedNode->renderer()) || replacedNode->isTextNode()) {
1056         ASSERT_NOT_REACHED();
1057         return nil;
1058     }
1059     
1060     // create an AX object, but skip it if it is not supposed to be seen
1061     RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document().axObjectCache()->getOrCreate(replacedNode->renderer());
1062     if (obj->accessibilityIsIgnored())
1063         return nil;
1064     
1065     // use the attachmentCharacter to represent the replaced node
1066     const UniChar attachmentChar = NSAttachmentCharacter;
1067     return [NSString stringWithCharacters:&attachmentChar length:1];
1068 }
1069
1070 - (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(id)textMarkerRange
1071 {
1072     if (!m_object)
1073         return nil;
1074     
1075     RefPtr<Range> range = [self rangeForTextMarkerRange:textMarkerRange];
1076     NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init];
1077     TextIterator it(range.get());
1078     while (!it.atEnd()) {
1079         // locate the node and starting offset for this range
1080         Node& node = it.range()->startContainer();
1081         ASSERT(&node == &it.range()->endContainer());
1082         int offset = it.range()->startOffset();
1083         
1084         // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
1085         if (it.text().length()) {
1086             // Add the text of the list marker item if necessary.
1087             String listMarkerText = m_object->listMarkerTextForNodeAndPosition(&node, VisiblePosition(it.range()->startPosition()));
1088             if (!listMarkerText.isEmpty())
1089                 AXAttributedStringAppendText(attrString, &node, listMarkerText);
1090             AXAttributedStringAppendText(attrString, &node, it.text());
1091         } else {
1092             Node* replacedNode = node.traverseToChildAt(offset);
1093             NSString *attachmentString = nsStringForReplacedNode(replacedNode);
1094             if (attachmentString) {
1095                 NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]);
1096                 
1097                 // append the placeholder string
1098                 [[attrString mutableString] appendString:attachmentString];
1099                 
1100                 // remove all inherited attributes
1101                 [attrString setAttributes:nil range:attrStringRange];
1102                 
1103                 // add the attachment attribute
1104                 AccessibilityObject* obj = replacedNode->renderer()->document().axObjectCache()->getOrCreate(replacedNode->renderer());
1105                 AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange);
1106             }
1107         }
1108         it.advance();
1109     }
1110     
1111     return [attrString autorelease];
1112 }
1113
1114 static id textMarkerRangeFromVisiblePositions(AXObjectCache* cache, const VisiblePosition& startPosition, const VisiblePosition& endPosition)
1115 {
1116     id startTextMarker = textMarkerForVisiblePosition(cache, startPosition);
1117     id endTextMarker = textMarkerForVisiblePosition(cache, endPosition);
1118     return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);
1119 }
1120
1121 - (id)textMarkerRangeFromVisiblePositions:(const VisiblePosition&)startPosition endPosition:(const VisiblePosition&)endPosition
1122 {
1123     return textMarkerRangeFromVisiblePositions(m_object->axObjectCache(), startPosition, endPosition);
1124 }
1125
1126 - (NSArray*)accessibilityActionNames
1127 {
1128     if (![self updateObjectBackingStore])
1129         return nil;
1130     
1131     // All elements should get ShowMenu and ScrollToVisible.
1132     // But certain earlier VoiceOver versions do not support scroll to visible, and it confuses them to see it in the list.
1133     static NSArray *defaultElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityShowMenuAction, NSAccessibilityScrollToVisibleAction, nil];
1134
1135     // Action elements allow Press.
1136     // 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.
1137     static NSArray *actionElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityPressAction, NSAccessibilityShowMenuAction, NSAccessibilityScrollToVisibleAction, nil];
1138
1139     // Menu elements allow Press and Cancel.
1140     static NSArray *menuElementActions = [[actionElementActions arrayByAddingObject:NSAccessibilityCancelAction] retain];
1141
1142     // Slider elements allow Increment/Decrement.
1143     static NSArray *sliderActions = [[defaultElementActions arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:NSAccessibilityIncrementAction, NSAccessibilityDecrementAction, nil]] retain];
1144     
1145     NSArray *actions;
1146     if (m_object->supportsPressAction())
1147         actions = actionElementActions;
1148     else if (m_object->isMenuRelated())
1149         actions = menuElementActions;
1150     else if (m_object->isSlider())
1151         actions = sliderActions;
1152     else if (m_object->isAttachment())
1153         actions = [[self attachmentView] accessibilityActionNames];
1154     else
1155         actions = defaultElementActions;
1156     
1157     return actions;
1158 }
1159
1160 - (NSArray*)additionalAccessibilityAttributeNames
1161 {
1162     if (!m_object)
1163         return nil;
1164     
1165     NSMutableArray *additional = [NSMutableArray array];
1166     if (m_object->supportsARIAOwns())
1167         [additional addObject:NSAccessibilityOwnsAttribute];
1168     
1169     if (m_object->isToggleButton())
1170         [additional addObject:NSAccessibilityValueAttribute];
1171     
1172     if (m_object->supportsExpanded() || m_object->isSummary())
1173         [additional addObject:NSAccessibilityExpandedAttribute];
1174     
1175     if (m_object->isScrollbar()
1176         || m_object->isRadioGroup()
1177         || m_object->isSplitter()
1178         || m_object->isToolbar())
1179         [additional addObject:NSAccessibilityOrientationAttribute];
1180     
1181     if (m_object->supportsARIADragging())
1182         [additional addObject:NSAccessibilityGrabbedAttribute];
1183     
1184     if (m_object->supportsARIADropping())
1185         [additional addObject:NSAccessibilityDropEffectsAttribute];
1186     
1187     if (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility() && downcast<AccessibilityTable>(*m_object).supportsSelectedRows())
1188         [additional addObject:NSAccessibilitySelectedRowsAttribute];
1189     
1190     if (m_object->supportsARIALiveRegion()) {
1191         [additional addObject:NSAccessibilityARIALiveAttribute];
1192         [additional addObject:NSAccessibilityARIARelevantAttribute];
1193     }
1194     
1195     if (m_object->supportsARIASetSize())
1196         [additional addObject:NSAccessibilityARIASetSizeAttribute];
1197     if (m_object->supportsARIAPosInSet())
1198         [additional addObject:NSAccessibilityARIAPosInSetAttribute];
1199     
1200     if (m_object->sortDirection() != SortDirectionNone)
1201         [additional addObject:NSAccessibilitySortDirectionAttribute];
1202     
1203     // If an object is a child of a live region, then add these
1204     if (m_object->isInsideARIALiveRegion())
1205         [additional addObject:NSAccessibilityARIAAtomicAttribute];
1206     // All objects should expose the ARIA busy attribute (ARIA 1.1 with ISSUE-538).
1207     [additional addObject:NSAccessibilityElementBusyAttribute];
1208     
1209     // Popup buttons on the Mac expose the value attribute.
1210     if (m_object->isPopUpButton()) {
1211         [additional addObject:NSAccessibilityValueAttribute];
1212     }
1213
1214     if (m_object->supportsDatetimeAttribute())
1215         [additional addObject:NSAccessibilityDatetimeValueAttribute];
1216     
1217     if (m_object->supportsRequiredAttribute()) {
1218         [additional addObject:NSAccessibilityRequiredAttribute];
1219     }
1220     
1221     if (m_object->ariaHasPopup())
1222         [additional addObject:NSAccessibilityHasPopupAttribute];
1223     
1224     if (m_object->isMathRoot()) {
1225         // The index of a square root is always known, so there's no object associated with it.
1226         if (!m_object->isMathSquareRoot())
1227             [additional addObject:NSAccessibilityMathRootIndexAttribute];
1228         [additional addObject:NSAccessibilityMathRootRadicandAttribute];
1229     } else if (m_object->isMathFraction()) {
1230         [additional addObject:NSAccessibilityMathFractionNumeratorAttribute];
1231         [additional addObject:NSAccessibilityMathFractionDenominatorAttribute];
1232         [additional addObject:NSAccessibilityMathLineThicknessAttribute];
1233     } else if (m_object->isMathSubscriptSuperscript()) {
1234         [additional addObject:NSAccessibilityMathBaseAttribute];
1235         [additional addObject:NSAccessibilityMathSubscriptAttribute];
1236         [additional addObject:NSAccessibilityMathSuperscriptAttribute];
1237     } else if (m_object->isMathUnderOver()) {
1238         [additional addObject:NSAccessibilityMathBaseAttribute];
1239         [additional addObject:NSAccessibilityMathUnderAttribute];
1240         [additional addObject:NSAccessibilityMathOverAttribute];
1241     } else if (m_object->isMathFenced()) {
1242         [additional addObject:NSAccessibilityMathFencedOpenAttribute];
1243         [additional addObject:NSAccessibilityMathFencedCloseAttribute];
1244     } else if (m_object->isMathMultiscript()) {
1245         [additional addObject:NSAccessibilityMathBaseAttribute];
1246         [additional addObject:NSAccessibilityMathPrescriptsAttribute];
1247         [additional addObject:NSAccessibilityMathPostscriptsAttribute];
1248     }
1249     
1250     if (m_object->supportsPath())
1251         [additional addObject:NSAccessibilityPathAttribute];
1252     
1253     if (m_object->supportsExpandedTextValue())
1254         [additional addObject:NSAccessibilityExpandedTextValueAttribute];
1255     
1256     return additional;
1257 }
1258
1259 - (NSArray*)accessibilityAttributeNames
1260 {
1261     if (![self updateObjectBackingStore])
1262         return nil;
1263     
1264     if (m_object->isAttachment())
1265         return [[self attachmentView] accessibilityAttributeNames];
1266     
1267     static NSArray* attributes = nil;
1268     static NSArray* anchorAttrs = nil;
1269     static NSArray* webAreaAttrs = nil;
1270     static NSArray* textAttrs = nil;
1271     static NSArray* listAttrs = nil;
1272     static NSArray* listBoxAttrs = nil;
1273     static NSArray* rangeAttrs = nil;
1274     static NSArray* commonMenuAttrs = nil;
1275     static NSArray* menuAttrs = nil;
1276     static NSArray* menuBarAttrs = nil;
1277     static NSArray* menuItemAttrs = nil;
1278     static NSArray* menuButtonAttrs = nil;
1279     static NSArray* controlAttrs = nil;
1280     static NSArray* tableAttrs = nil;
1281     static NSArray* tableRowAttrs = nil;
1282     static NSArray* tableColAttrs = nil;
1283     static NSArray* tableCellAttrs = nil;
1284     static NSArray* groupAttrs = nil;
1285     static NSArray* inputImageAttrs = nil;
1286     static NSArray* passwordFieldAttrs = nil;
1287     static NSArray* tabListAttrs = nil;
1288     static NSArray* comboBoxAttrs = nil;
1289     static NSArray* outlineAttrs = nil;
1290     static NSArray* outlineRowAttrs = nil;
1291     static NSArray* buttonAttrs = nil;
1292     static NSArray* scrollViewAttrs = nil;
1293     static NSArray* incrementorAttrs = nil;
1294     NSMutableArray* tempArray;
1295     if (attributes == nil) {
1296         attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1297             NSAccessibilitySubroleAttribute,
1298             NSAccessibilityRoleDescriptionAttribute,
1299             NSAccessibilityChildrenAttribute,
1300             NSAccessibilityHelpAttribute,
1301             NSAccessibilityParentAttribute,
1302             NSAccessibilityPositionAttribute,
1303             NSAccessibilitySizeAttribute,
1304             NSAccessibilityTitleAttribute,
1305             NSAccessibilityDescriptionAttribute,
1306             NSAccessibilityValueAttribute,
1307             NSAccessibilityFocusedAttribute,
1308             NSAccessibilityEnabledAttribute,
1309             NSAccessibilityWindowAttribute,
1310             @"AXSelectedTextMarkerRange",
1311             @"AXStartTextMarker",
1312             @"AXEndTextMarker",
1313             @"AXVisited",
1314             NSAccessibilityLinkedUIElementsAttribute,
1315             NSAccessibilitySelectedAttribute,
1316             NSAccessibilityBlockQuoteLevelAttribute,
1317             NSAccessibilityTopLevelUIElementAttribute,
1318             NSAccessibilityLanguageAttribute,
1319             NSAccessibilityDOMIdentifierAttribute,
1320             NSAccessibilityDOMClassListAttribute,
1321             NSAccessibilityFocusableAncestorAttribute,
1322             NSAccessibilityEditableAncestorAttribute,
1323             NSAccessibilityHighestEditableAncestorAttribute,
1324             nil];
1325     }
1326     if (commonMenuAttrs == nil) {
1327         commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1328                            NSAccessibilityRoleDescriptionAttribute,
1329                            NSAccessibilityChildrenAttribute,
1330                            NSAccessibilityParentAttribute,
1331                            NSAccessibilityEnabledAttribute,
1332                            NSAccessibilityPositionAttribute,
1333                            NSAccessibilitySizeAttribute,
1334                            nil];
1335     }
1336     if (anchorAttrs == nil) {
1337         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1338         [tempArray addObject:NSAccessibilityURLAttribute];
1339         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1340         anchorAttrs = [[NSArray alloc] initWithArray:tempArray];
1341         [tempArray release];
1342     }
1343     if (webAreaAttrs == nil) {
1344         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1345         // WebAreas should not expose AXSubrole.
1346         [tempArray removeObject:NSAccessibilitySubroleAttribute];
1347         // WebAreas should not expose ancestor attributes
1348         [tempArray removeObject:NSAccessibilityFocusableAncestorAttribute];
1349         [tempArray removeObject:NSAccessibilityEditableAncestorAttribute];
1350         [tempArray removeObject:NSAccessibilityHighestEditableAncestorAttribute];
1351         [tempArray addObject:@"AXLinkUIElements"];
1352         [tempArray addObject:@"AXLoaded"];
1353         [tempArray addObject:@"AXLayoutCount"];
1354         [tempArray addObject:NSAccessibilityLoadingProgressAttribute];
1355         [tempArray addObject:NSAccessibilityURLAttribute];
1356         [tempArray addObject:NSAccessibilityCaretBrowsingEnabledAttribute];
1357         [tempArray addObject:NSAccessibilityPreventKeyboardDOMEventDispatchAttribute];
1358         webAreaAttrs = [[NSArray alloc] initWithArray:tempArray];
1359         [tempArray release];
1360     }
1361     if (textAttrs == nil) {
1362         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1363         [tempArray addObject:NSAccessibilityNumberOfCharactersAttribute];
1364         [tempArray addObject:NSAccessibilitySelectedTextAttribute];
1365         [tempArray addObject:NSAccessibilitySelectedTextRangeAttribute];
1366         [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute];
1367         [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute];
1368         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1369         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1370         [tempArray addObject:NSAccessibilityRequiredAttribute];
1371         [tempArray addObject:NSAccessibilityInvalidAttribute];
1372         [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1373         [tempArray addObject:NSAccessibilityValueAutofilledAttribute];
1374         textAttrs = [[NSArray alloc] initWithArray:tempArray];
1375         [tempArray release];
1376     }
1377     if (listAttrs == nil) {
1378         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1379         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1380         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1381         [tempArray addObject:NSAccessibilityOrientationAttribute];
1382         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1383         listAttrs = [[NSArray alloc] initWithArray:tempArray];
1384         [tempArray release];
1385     }
1386     if (listBoxAttrs == nil) {
1387         tempArray = [[NSMutableArray alloc] initWithArray:listAttrs];
1388         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1389         [tempArray addObject:NSAccessibilityRequiredAttribute];
1390         [tempArray addObject:NSAccessibilityInvalidAttribute];
1391         [tempArray addObject:NSAccessibilityOrientationAttribute];
1392         listBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1393         [tempArray release];
1394     }
1395     if (rangeAttrs == nil) {
1396         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1397         [tempArray addObject:NSAccessibilityMinValueAttribute];
1398         [tempArray addObject:NSAccessibilityMaxValueAttribute];
1399         [tempArray addObject:NSAccessibilityOrientationAttribute];
1400         [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1401         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1402         rangeAttrs = [[NSArray alloc] initWithArray:tempArray];
1403         [tempArray release];
1404     }
1405     if (menuBarAttrs == nil) {
1406         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1407         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1408         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1409         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1410         [tempArray addObject:NSAccessibilityOrientationAttribute];
1411         menuBarAttrs = [[NSArray alloc] initWithArray:tempArray];
1412         [tempArray release];
1413     }
1414     if (menuAttrs == nil) {
1415         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1416         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1417         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1418         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1419         [tempArray addObject:NSAccessibilityOrientationAttribute];
1420         menuAttrs = [[NSArray alloc] initWithArray:tempArray];
1421         [tempArray release];
1422     }
1423     if (menuItemAttrs == nil) {
1424         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1425         [tempArray addObject:NSAccessibilityTitleAttribute];
1426         [tempArray addObject:NSAccessibilityDescriptionAttribute];
1427         [tempArray addObject:NSAccessibilityHelpAttribute];
1428         [tempArray addObject:NSAccessibilitySelectedAttribute];
1429         [tempArray addObject:NSAccessibilityValueAttribute];
1430         [tempArray addObject:(NSString*)kAXMenuItemCmdCharAttribute];
1431         [tempArray addObject:(NSString*)kAXMenuItemCmdVirtualKeyAttribute];
1432         [tempArray addObject:(NSString*)kAXMenuItemCmdGlyphAttribute];
1433         [tempArray addObject:(NSString*)kAXMenuItemCmdModifiersAttribute];
1434         [tempArray addObject:(NSString*)kAXMenuItemMarkCharAttribute];
1435         [tempArray addObject:(NSString*)kAXMenuItemPrimaryUIElementAttribute];
1436         [tempArray addObject:NSAccessibilityServesAsTitleForUIElementsAttribute];
1437         [tempArray addObject:NSAccessibilityFocusedAttribute];
1438         menuItemAttrs = [[NSArray alloc] initWithArray:tempArray];
1439         [tempArray release];
1440     }
1441     if (menuButtonAttrs == nil) {
1442         menuButtonAttrs = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute,
1443                            NSAccessibilityRoleDescriptionAttribute,
1444                            NSAccessibilityParentAttribute,
1445                            NSAccessibilityPositionAttribute,
1446                            NSAccessibilitySizeAttribute,
1447                            NSAccessibilityWindowAttribute,
1448                            NSAccessibilityEnabledAttribute,
1449                            NSAccessibilityFocusedAttribute,
1450                            NSAccessibilityTitleAttribute,
1451                            NSAccessibilityChildrenAttribute, nil];
1452     }
1453     if (controlAttrs == nil) {
1454         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1455         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1456         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1457         [tempArray addObject:NSAccessibilityRequiredAttribute];
1458         [tempArray addObject:NSAccessibilityInvalidAttribute];
1459         controlAttrs = [[NSArray alloc] initWithArray:tempArray];
1460         [tempArray release];
1461     }
1462     if (incrementorAttrs == nil) {
1463         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1464         [tempArray addObject:NSAccessibilityIncrementButtonAttribute];
1465         [tempArray addObject:NSAccessibilityDecrementButtonAttribute];
1466         [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1467         [tempArray addObject:NSAccessibilityMinValueAttribute];
1468         [tempArray addObject:NSAccessibilityMaxValueAttribute];
1469         incrementorAttrs = [[NSArray alloc] initWithArray:tempArray];
1470         [tempArray release];
1471     }
1472     if (buttonAttrs == nil) {
1473         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1474         // Buttons should not expose AXValue.
1475         [tempArray removeObject:NSAccessibilityValueAttribute];
1476         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1477         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1478         buttonAttrs = [[NSArray alloc] initWithArray:tempArray];
1479         [tempArray release];
1480     }
1481     if (comboBoxAttrs == nil) {
1482         tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs];
1483         [tempArray addObject:NSAccessibilityExpandedAttribute];
1484         [tempArray addObject:NSAccessibilityOrientationAttribute];
1485         comboBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1486         [tempArray release];
1487     }
1488     if (tableAttrs == nil) {
1489         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1490         [tempArray addObject:NSAccessibilityRowsAttribute];
1491         [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1492         [tempArray addObject:NSAccessibilityColumnsAttribute];
1493         [tempArray addObject:NSAccessibilityVisibleColumnsAttribute];
1494         [tempArray addObject:NSAccessibilityVisibleCellsAttribute];
1495         [tempArray addObject:NSAccessibilityColumnHeaderUIElementsAttribute];
1496         [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1497         [tempArray addObject:NSAccessibilityHeaderAttribute];
1498         [tempArray addObject:NSAccessibilityColumnCountAttribute];
1499         [tempArray addObject:NSAccessibilityRowCountAttribute];
1500         [tempArray addObject:NSAccessibilityARIAColumnCountAttribute];
1501         [tempArray addObject:NSAccessibilityARIARowCountAttribute];
1502         tableAttrs = [[NSArray alloc] initWithArray:tempArray];
1503         [tempArray release];
1504     }
1505     if (tableRowAttrs == nil) {
1506         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1507         [tempArray addObject:NSAccessibilityIndexAttribute];
1508         tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1509         [tempArray release];
1510     }
1511     if (tableColAttrs == nil) {
1512         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1513         [tempArray addObject:NSAccessibilityIndexAttribute];
1514         [tempArray addObject:NSAccessibilityHeaderAttribute];
1515         [tempArray addObject:NSAccessibilityRowsAttribute];
1516         [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1517         tableColAttrs = [[NSArray alloc] initWithArray:tempArray];
1518         [tempArray release];
1519     }
1520     if (tableCellAttrs == nil) {
1521         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1522         [tempArray addObject:NSAccessibilityRowIndexRangeAttribute];
1523         [tempArray addObject:NSAccessibilityColumnIndexRangeAttribute];
1524         [tempArray addObject:NSAccessibilityColumnHeaderUIElementsAttribute];
1525         [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1526         [tempArray addObject:NSAccessibilityARIAColumnIndexAttribute];
1527         [tempArray addObject:NSAccessibilityARIARowIndexAttribute];
1528         tableCellAttrs = [[NSArray alloc] initWithArray:tempArray];
1529         [tempArray release];
1530     }
1531     if (groupAttrs == nil) {
1532         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1533         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1534         groupAttrs = [[NSArray alloc] initWithArray:tempArray];
1535         [tempArray release];
1536     }
1537     if (inputImageAttrs == nil) {
1538         tempArray = [[NSMutableArray alloc] initWithArray:buttonAttrs];
1539         [tempArray addObject:NSAccessibilityURLAttribute];
1540         inputImageAttrs = [[NSArray alloc] initWithArray:tempArray];
1541         [tempArray release];
1542     }
1543     if (passwordFieldAttrs == nil) {
1544         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1545         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1546         [tempArray addObject:NSAccessibilityRequiredAttribute];
1547         [tempArray addObject:NSAccessibilityInvalidAttribute];
1548         [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1549         [tempArray addObject:NSAccessibilityValueAutofilledAttribute];
1550         passwordFieldAttrs = [[NSArray alloc] initWithArray:tempArray];
1551         [tempArray release];
1552     }
1553     if (tabListAttrs == nil) {
1554         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1555         [tempArray addObject:NSAccessibilityTabsAttribute];
1556         [tempArray addObject:NSAccessibilityContentsAttribute];
1557         [tempArray addObject:NSAccessibilityOrientationAttribute];
1558         tabListAttrs = [[NSArray alloc] initWithArray:tempArray];
1559         [tempArray release];
1560     }
1561     if (outlineAttrs == nil) {
1562         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1563         [tempArray addObject:NSAccessibilitySelectedRowsAttribute];
1564         [tempArray addObject:NSAccessibilityRowsAttribute];
1565         [tempArray addObject:NSAccessibilityColumnsAttribute];
1566         [tempArray addObject:NSAccessibilityOrientationAttribute];
1567         outlineAttrs = [[NSArray alloc] initWithArray:tempArray];
1568         [tempArray release];
1569     }
1570     if (outlineRowAttrs == nil) {
1571         tempArray = [[NSMutableArray alloc] initWithArray:tableRowAttrs];
1572         [tempArray addObject:NSAccessibilityDisclosingAttribute];
1573         [tempArray addObject:NSAccessibilityDisclosedByRowAttribute];
1574         [tempArray addObject:NSAccessibilityDisclosureLevelAttribute];
1575         [tempArray addObject:NSAccessibilityDisclosedRowsAttribute];
1576         outlineRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1577         [tempArray release];
1578     }
1579     if (scrollViewAttrs == nil) {
1580         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1581         [tempArray addObject:NSAccessibilityContentsAttribute];
1582         [tempArray addObject:NSAccessibilityHorizontalScrollBarAttribute];
1583         [tempArray addObject:NSAccessibilityVerticalScrollBarAttribute];
1584         scrollViewAttrs = [[NSArray alloc] initWithArray:tempArray];
1585         [tempArray release];
1586     }
1587     
1588     NSArray *objectAttributes = attributes;
1589     
1590     if (m_object->isPasswordField())
1591         objectAttributes = passwordFieldAttrs;
1592     
1593     else if (m_object->isWebArea())
1594         objectAttributes = webAreaAttrs;
1595     
1596     else if (m_object->isTextControl())
1597         objectAttributes = textAttrs;
1598     
1599     else if (m_object->isLink() || m_object->isImage())
1600         objectAttributes = anchorAttrs;
1601     
1602     else if (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility())
1603         objectAttributes = tableAttrs;
1604     else if (m_object->isTableColumn())
1605         objectAttributes = tableColAttrs;
1606     else if (m_object->isTableCell())
1607         objectAttributes = tableCellAttrs;
1608     else if (m_object->isTableRow()) {
1609         // An ARIA table row can be collapsed and expanded, so it needs the extra attributes.
1610         if (m_object->isARIATreeGridRow())
1611             objectAttributes = outlineRowAttrs;
1612         else
1613             objectAttributes = tableRowAttrs;
1614     }
1615     
1616     else if (m_object->isTree())
1617         objectAttributes = outlineAttrs;
1618     else if (m_object->isTreeItem())
1619         objectAttributes = outlineRowAttrs;
1620     
1621     else if (m_object->isListBox())
1622         objectAttributes = listBoxAttrs;
1623     else if (m_object->isList())
1624         objectAttributes = listAttrs;
1625     
1626     else if (m_object->isComboBox())
1627         objectAttributes = comboBoxAttrs;
1628     
1629     else if (m_object->isProgressIndicator() || m_object->isSlider())
1630         objectAttributes = rangeAttrs;
1631     
1632     // These are processed in order because an input image is a button, and a button is a control.
1633     else if (m_object->isInputImage())
1634         objectAttributes = inputImageAttrs;
1635     else if (m_object->isButton())
1636         objectAttributes = buttonAttrs;
1637     else if (m_object->isControl())
1638         objectAttributes = controlAttrs;
1639     
1640     else if (m_object->isGroup() || m_object->isListItem())
1641         objectAttributes = groupAttrs;
1642     else if (m_object->isTabList())
1643         objectAttributes = tabListAttrs;
1644     else if (m_object->isScrollView())
1645         objectAttributes = scrollViewAttrs;
1646     else if (m_object->isSpinButton())
1647         objectAttributes = incrementorAttrs;
1648     
1649     else if (m_object->isMenu())
1650         objectAttributes = menuAttrs;
1651     else if (m_object->isMenuBar())
1652         objectAttributes = menuBarAttrs;
1653     else if (m_object->isMenuButton())
1654         objectAttributes = menuButtonAttrs;
1655     else if (m_object->isMenuItem())
1656         objectAttributes = menuItemAttrs;
1657     
1658     NSArray *additionalAttributes = [self additionalAccessibilityAttributeNames];
1659     if ([additionalAttributes count])
1660         objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:additionalAttributes];
1661     
1662     // Only expose AXARIACurrent attribute when the element is set to be current item.
1663     if (m_object->ariaCurrentState() != ARIACurrentFalse)
1664         objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:@[ NSAccessibilityARIACurrentAttribute ]];
1665     
1666     return objectAttributes;
1667 }
1668
1669 - (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(id)textMarkerRange
1670 {
1671     if (!textMarkerRange)
1672         return VisiblePositionRange();
1673     AXObjectCache* cache = m_object->axObjectCache();
1674     return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(cache, textMarkerRange), visiblePositionForEndOfTextMarkerRange(cache, textMarkerRange));
1675 }
1676
1677 - (NSArray*)renderWidgetChildren
1678 {
1679     Widget* widget = m_object->widget();
1680     if (!widget)
1681         return nil;
1682 #pragma clang diagnostic push
1683 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1684     return [(widget->platformWidget()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute];
1685 #pragma clang diagnostic pop
1686 }
1687
1688 - (id)remoteAccessibilityParentObject
1689 {
1690     if (!m_object)
1691         return nil;
1692     
1693     Document* document = m_object->document();
1694     if (!document)
1695         return nil;
1696     
1697     Frame* frame = document->frame();
1698     if (!frame)
1699         return nil;
1700     
1701     return frame->loader().client().accessibilityRemoteObject();
1702 }
1703
1704 static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector)
1705 {
1706     unsigned length = [array count];
1707     vector.reserveInitialCapacity(length);
1708     for (unsigned i = 0; i < length; ++i) {
1709         AccessibilityObject* obj = [[array objectAtIndex:i] accessibilityObject];
1710         if (obj)
1711             vector.append(obj);
1712     }
1713 }
1714
1715 static NSMutableArray *convertStringsToNSArray(const Vector<String>& vector)
1716 {
1717     NSMutableArray *array = [NSMutableArray arrayWithCapacity:vector.size()];
1718     for (const auto& string : vector)
1719         [array addObject:string];
1720     return array;
1721 }
1722
1723 - (id)textMarkerRangeForSelection
1724 {
1725     VisibleSelection selection = m_object->selection();
1726     if (selection.isNone())
1727         return nil;
1728     return [self textMarkerRangeFromVisiblePositions:selection.visibleStart() endPosition:selection.visibleEnd()];
1729 }
1730
1731 - (id)associatedPluginParent
1732 {
1733     if (!m_object || !m_object->hasAttribute(x_apple_pdf_annotationAttr))
1734         return nil;
1735     
1736     if (!m_object->document()->isPluginDocument())
1737         return nil;
1738         
1739     Widget* pluginWidget = static_cast<PluginDocument*>(m_object->document())->pluginWidget();
1740     if (!pluginWidget || !pluginWidget->isPluginViewBase())
1741         return nil;
1742
1743     return static_cast<PluginViewBase*>(pluginWidget)->accessibilityAssociatedPluginParentForElement(m_object->element());
1744 }
1745
1746 - (CGPoint)convertPointToScreenSpace:(FloatPoint &)point
1747 {
1748     FrameView* frameView = m_object->documentFrameView();
1749     
1750     // WebKit1 code path... platformWidget() exists.
1751     if (frameView && frameView->platformWidget()) {
1752         NSPoint nsPoint = (NSPoint)point;
1753         NSView* view = frameView->documentView();
1754 #pragma clang diagnostic push
1755 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1756         nsPoint = [[view window] convertBaseToScreen:[view convertPoint:nsPoint toView:nil]];
1757 #pragma clang diagnostic pop
1758         return CGPointMake(nsPoint.x, nsPoint.y);
1759     } else {
1760         
1761         // Find the appropriate scroll view to use to convert the contents to the window.
1762         ScrollView* scrollView = nullptr;
1763         AccessibilityObject* parent = nullptr;
1764         for (parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
1765             if (is<AccessibilityScrollView>(*parent)) {
1766                 scrollView = downcast<AccessibilityScrollView>(*parent).scrollView();
1767                 break;
1768             }
1769         }
1770         
1771         IntPoint intPoint = flooredIntPoint(point);
1772         if (scrollView)
1773             intPoint = scrollView->contentsToRootView(intPoint);
1774         
1775         Page* page = m_object->page();
1776         
1777         // If we have an empty chrome client (like SVG) then we should use the page
1778         // of the scroll view parent to help us get to the screen rect.
1779         if (parent && page && page->chrome().client().isEmptyChromeClient())
1780             page = parent->page();
1781         
1782         if (page) {
1783             IntRect rect = IntRect(intPoint, IntSize(0, 0));            
1784             intPoint = page->chrome().rootViewToScreen(rect).location();
1785         }
1786         
1787         return intPoint;
1788     }
1789 }
1790
1791 static void WebTransformCGPathToNSBezierPath(void *info, const CGPathElement *element)
1792 {
1793     NSBezierPath *bezierPath = (NSBezierPath *)info;
1794     switch (element->type) {
1795     case kCGPathElementMoveToPoint:
1796         [bezierPath moveToPoint:NSPointFromCGPoint(element->points[0])];
1797         break;
1798     case kCGPathElementAddLineToPoint:
1799         [bezierPath lineToPoint:NSPointFromCGPoint(element->points[0])];
1800         break;
1801     case kCGPathElementAddCurveToPoint:
1802         [bezierPath curveToPoint:NSPointFromCGPoint(element->points[0]) controlPoint1:NSPointFromCGPoint(element->points[1]) controlPoint2:NSPointFromCGPoint(element->points[2])];
1803         break;
1804     case kCGPathElementCloseSubpath:
1805         [bezierPath closePath];
1806         break;
1807     default:
1808         break;
1809     }
1810 }
1811
1812 - (NSBezierPath *)bezierPathFromPath:(CGPathRef)path
1813 {
1814     NSBezierPath *bezierPath = [NSBezierPath bezierPath];
1815     CGPathApply(path, bezierPath, WebTransformCGPathToNSBezierPath);
1816     return bezierPath;
1817 }
1818
1819 - (NSBezierPath *)path
1820 {
1821     Path path = m_object->elementPath();
1822     if (path.isEmpty())
1823         return NULL;
1824     
1825     CGPathRef transformedPath = [self convertPathToScreenSpace:path];
1826     return [self bezierPathFromPath:transformedPath];
1827 }
1828
1829 - (NSValue *)position
1830 {
1831     IntRect rect = snappedIntRect(m_object->elementRect());
1832     
1833     // The Cocoa accessibility API wants the lower-left corner.
1834     FloatPoint floatPoint = FloatPoint(rect.x(), rect.maxY());
1835
1836     CGPoint cgPoint = [self convertPointToScreenSpace:floatPoint];
1837     
1838     return [NSValue valueWithPoint:NSMakePoint(cgPoint.x, cgPoint.y)];
1839 }
1840
1841 typedef HashMap<int, NSString*> AccessibilityRoleMap;
1842
1843 static const AccessibilityRoleMap& createAccessibilityRoleMap()
1844 {
1845     struct RoleEntry {
1846         AccessibilityRole value;
1847         NSString* string;
1848     };
1849     
1850     static const RoleEntry roles[] = {
1851         { UnknownRole, NSAccessibilityUnknownRole },
1852         { ButtonRole, NSAccessibilityButtonRole },
1853         { RadioButtonRole, NSAccessibilityRadioButtonRole },
1854         { CheckBoxRole, NSAccessibilityCheckBoxRole },
1855         { SliderRole, NSAccessibilitySliderRole },
1856         { TabGroupRole, NSAccessibilityTabGroupRole },
1857         { TextFieldRole, NSAccessibilityTextFieldRole },
1858         { StaticTextRole, NSAccessibilityStaticTextRole },
1859         { TextAreaRole, NSAccessibilityTextAreaRole },
1860         { ScrollAreaRole, NSAccessibilityScrollAreaRole },
1861         { PopUpButtonRole, NSAccessibilityPopUpButtonRole },
1862         { MenuButtonRole, NSAccessibilityMenuButtonRole },
1863         { TableRole, NSAccessibilityTableRole },
1864         { ApplicationRole, NSAccessibilityApplicationRole },
1865         { GroupRole, NSAccessibilityGroupRole },
1866         { TextGroupRole, NSAccessibilityGroupRole },
1867         { RadioGroupRole, NSAccessibilityRadioGroupRole },
1868         { ListRole, NSAccessibilityListRole },
1869         { DirectoryRole, NSAccessibilityListRole },
1870         { ScrollBarRole, NSAccessibilityScrollBarRole },
1871         { ValueIndicatorRole, NSAccessibilityValueIndicatorRole },
1872         { ImageRole, NSAccessibilityImageRole },
1873         { MenuBarRole, NSAccessibilityMenuBarRole },
1874         { MenuRole, NSAccessibilityMenuRole },
1875         { MenuItemRole, NSAccessibilityMenuItemRole },
1876         { MenuItemCheckboxRole, NSAccessibilityMenuItemRole },
1877         { MenuItemRadioRole, NSAccessibilityMenuItemRole },
1878         { ColumnRole, NSAccessibilityColumnRole },
1879         { RowRole, NSAccessibilityRowRole },
1880         { ToolbarRole, NSAccessibilityToolbarRole },
1881         { BusyIndicatorRole, NSAccessibilityBusyIndicatorRole },
1882         { ProgressIndicatorRole, NSAccessibilityProgressIndicatorRole },
1883         { WindowRole, NSAccessibilityWindowRole },
1884         { DrawerRole, NSAccessibilityDrawerRole },
1885         { SystemWideRole, NSAccessibilitySystemWideRole },
1886         { OutlineRole, NSAccessibilityOutlineRole },
1887         { IncrementorRole, NSAccessibilityIncrementorRole },
1888         { BrowserRole, NSAccessibilityBrowserRole },
1889         { ComboBoxRole, NSAccessibilityComboBoxRole },
1890         { SplitGroupRole, NSAccessibilitySplitGroupRole },
1891         { SplitterRole, NSAccessibilitySplitterRole },
1892         { ColorWellRole, NSAccessibilityColorWellRole },
1893         { GrowAreaRole, NSAccessibilityGrowAreaRole },
1894         { SheetRole, NSAccessibilitySheetRole },
1895         { HelpTagRole, NSAccessibilityHelpTagRole },
1896         { MatteRole, NSAccessibilityMatteRole },
1897         { RulerRole, NSAccessibilityRulerRole },
1898         { RulerMarkerRole, NSAccessibilityRulerMarkerRole },
1899         { LinkRole, NSAccessibilityLinkRole },
1900         { DisclosureTriangleRole, NSAccessibilityDisclosureTriangleRole },
1901         { GridRole, NSAccessibilityTableRole },
1902         { TreeGridRole, NSAccessibilityTableRole },
1903         { WebCoreLinkRole, NSAccessibilityLinkRole },
1904         { ImageMapLinkRole, NSAccessibilityLinkRole },
1905         { ImageMapRole, @"AXImageMap" },
1906         { ListMarkerRole, @"AXListMarker" },
1907         { WebAreaRole, @"AXWebArea" },
1908         { HeadingRole, @"AXHeading" },
1909         { ListBoxRole, NSAccessibilityListRole },
1910         { ListBoxOptionRole, NSAccessibilityStaticTextRole },
1911         { CellRole, NSAccessibilityCellRole },
1912         { GridCellRole, NSAccessibilityCellRole },
1913         { TableHeaderContainerRole, NSAccessibilityGroupRole },
1914         { ColumnHeaderRole, NSAccessibilityCellRole },
1915         { RowHeaderRole, NSAccessibilityCellRole },
1916         { DefinitionRole, NSAccessibilityGroupRole },
1917         { DescriptionListDetailRole, NSAccessibilityGroupRole },
1918         { DescriptionListTermRole, NSAccessibilityGroupRole },
1919         { TermRole, NSAccessibilityGroupRole },
1920         { DescriptionListRole, NSAccessibilityListRole },
1921         { SliderThumbRole, NSAccessibilityValueIndicatorRole },
1922         { WebApplicationRole, NSAccessibilityGroupRole },
1923         { LandmarkBannerRole, NSAccessibilityGroupRole },
1924         { LandmarkComplementaryRole, NSAccessibilityGroupRole },
1925         { LandmarkDocRegionRole, NSAccessibilityGroupRole },
1926         { LandmarkContentInfoRole, NSAccessibilityGroupRole },
1927         { LandmarkMainRole, NSAccessibilityGroupRole },
1928         { LandmarkNavigationRole, NSAccessibilityGroupRole },
1929         { LandmarkRegionRole, NSAccessibilityGroupRole },
1930         { LandmarkSearchRole, NSAccessibilityGroupRole },
1931         { ApplicationAlertRole, NSAccessibilityGroupRole },
1932         { ApplicationAlertDialogRole, NSAccessibilityGroupRole },
1933         { ApplicationDialogRole, NSAccessibilityGroupRole },
1934         { ApplicationGroupRole, NSAccessibilityGroupRole },
1935         { ApplicationTextGroupRole, NSAccessibilityGroupRole },
1936         { ApplicationLogRole, NSAccessibilityGroupRole },
1937         { ApplicationMarqueeRole, NSAccessibilityGroupRole },
1938         { ApplicationStatusRole, NSAccessibilityGroupRole },
1939         { ApplicationTimerRole, NSAccessibilityGroupRole },
1940         { DocumentRole, NSAccessibilityGroupRole },
1941         { DocumentArticleRole, NSAccessibilityGroupRole },
1942         { DocumentMathRole, NSAccessibilityGroupRole },
1943         { DocumentNoteRole, NSAccessibilityGroupRole },
1944         { UserInterfaceTooltipRole, NSAccessibilityGroupRole },
1945         { TabRole, NSAccessibilityRadioButtonRole },
1946         { TabListRole, NSAccessibilityTabGroupRole },
1947         { TabPanelRole, NSAccessibilityGroupRole },
1948         { TreeRole, NSAccessibilityOutlineRole },
1949         { TreeItemRole, NSAccessibilityRowRole },
1950         { ListItemRole, NSAccessibilityGroupRole },
1951         { ParagraphRole, NSAccessibilityGroupRole },
1952         { LabelRole, NSAccessibilityGroupRole },
1953         { DivRole, NSAccessibilityGroupRole },
1954         { FormRole, NSAccessibilityGroupRole },
1955         { SpinButtonRole, NSAccessibilityIncrementorRole },
1956         { FooterRole, NSAccessibilityGroupRole },
1957         { ToggleButtonRole, NSAccessibilityCheckBoxRole },
1958         { CanvasRole, NSAccessibilityImageRole },
1959         { SVGRootRole, NSAccessibilityGroupRole },
1960         { LegendRole, NSAccessibilityGroupRole },
1961         { MathElementRole, NSAccessibilityGroupRole },
1962         { AudioRole, NSAccessibilityGroupRole },
1963         { VideoRole, NSAccessibilityGroupRole },
1964         { HorizontalRuleRole, NSAccessibilitySplitterRole },
1965         { BlockquoteRole, NSAccessibilityGroupRole },
1966         { SwitchRole, NSAccessibilityCheckBoxRole },
1967         { SearchFieldRole, NSAccessibilityTextFieldRole },
1968         { PreRole, NSAccessibilityGroupRole },
1969         { RubyBaseRole, NSAccessibilityGroupRole },
1970         { RubyBlockRole, NSAccessibilityGroupRole },
1971         { RubyInlineRole, NSAccessibilityGroupRole },
1972         { RubyRunRole, NSAccessibilityGroupRole },
1973         { RubyTextRole, NSAccessibilityGroupRole },
1974         { DetailsRole, NSAccessibilityGroupRole },
1975         { SummaryRole, NSAccessibilityButtonRole },
1976         { SVGTextPathRole, NSAccessibilityGroupRole },
1977         { SVGTextRole, NSAccessibilityGroupRole },
1978         { SVGTSpanRole, NSAccessibilityGroupRole },
1979         { InlineRole, NSAccessibilityGroupRole },
1980         { MarkRole, NSAccessibilityGroupRole },
1981         { TimeRole, NSAccessibilityGroupRole },
1982         { FeedRole, NSAccessibilityGroupRole },
1983         { FigureRole, NSAccessibilityGroupRole },
1984         { FootnoteRole, NSAccessibilityGroupRole },
1985     };
1986     AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;
1987     
1988     const unsigned numRoles = sizeof(roles) / sizeof(roles[0]);
1989     for (unsigned i = 0; i < numRoles; ++i)
1990         roleMap.set(roles[i].value, roles[i].string);
1991     return roleMap;
1992 }
1993
1994 static NSString* roleValueToNSString(AccessibilityRole value)
1995 {
1996     ASSERT(value);
1997     static const AccessibilityRoleMap& roleMap = createAccessibilityRoleMap();
1998     return roleMap.get(value);
1999 }
2000
2001 - (NSString*)role
2002 {
2003 #pragma clang diagnostic push
2004 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2005     if (m_object->isAttachment())
2006         return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute];
2007 #pragma clang diagnostic pop
2008     AccessibilityRole role = m_object->roleValue();
2009
2010     if (role == LabelRole && is<AccessibilityLabel>(*m_object) && downcast<AccessibilityLabel>(*m_object).containsOnlyStaticText())
2011         role = StaticTextRole;
2012
2013     // The mfenced element creates anonymous RenderMathMLOperators with no RenderText
2014     // descendants. Because these anonymous renderers are the only accessible objects
2015     // containing the operator, assign StaticTextRole.
2016     if (m_object->isAnonymousMathOperator())
2017         role = StaticTextRole;
2018
2019     if (role == CanvasRole && m_object->canvasHasFallbackContent())
2020         role = GroupRole;
2021     NSString* string = roleValueToNSString(role);
2022     if (string != nil)
2023         return string;
2024     return NSAccessibilityUnknownRole;
2025 }
2026
2027 #pragma clang diagnostic push
2028 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2029 - (NSString*)subrole
2030 {
2031     if (m_object->isPasswordField())
2032         return NSAccessibilitySecureTextFieldSubrole;
2033     if (m_object->isSearchField())
2034         return NSAccessibilitySearchFieldSubrole;
2035     
2036     if (m_object->isAttachment()) {
2037         NSView* attachView = [self attachmentView];
2038         if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute])
2039             return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute];
2040     }
2041     
2042     AccessibilityRole role = m_object->roleValue();
2043     if (role == HorizontalRuleRole)
2044         return NSAccessibilityContentSeparatorSubrole;
2045     if (role == ToggleButtonRole)
2046         return NSAccessibilityToggleSubrole;
2047     
2048     if (is<AccessibilitySpinButtonPart>(*m_object)) {
2049         if (downcast<AccessibilitySpinButtonPart>(*m_object).isIncrementor())
2050             return NSAccessibilityIncrementArrowSubrole;
2051         
2052         return NSAccessibilityDecrementArrowSubrole;
2053     }
2054     
2055     if (m_object->isFileUploadButton())
2056         return @"AXFileUploadButton";
2057     
2058     if (m_object->isTreeItem())
2059         return NSAccessibilityOutlineRowSubrole;
2060     
2061     if (m_object->isFieldset())
2062         return @"AXFieldset";
2063     
2064     if (is<AccessibilityList>(*m_object)) {
2065         auto& listObject = downcast<AccessibilityList>(*m_object);
2066         if (listObject.isUnorderedList() || listObject.isOrderedList())
2067             return NSAccessibilityContentListSubrole;
2068         if (listObject.isDescriptionList()) {
2069             return NSAccessibilityDescriptionListSubrole;
2070         }
2071     }
2072     
2073     // ARIA content subroles.
2074     switch (role) {
2075         case LandmarkBannerRole:
2076             return @"AXLandmarkBanner";
2077         case LandmarkComplementaryRole:
2078             return @"AXLandmarkComplementary";
2079             // Footer roles should appear as content info types.
2080         case FooterRole:
2081         case LandmarkContentInfoRole:
2082             return @"AXLandmarkContentInfo";
2083         case LandmarkMainRole:
2084             return @"AXLandmarkMain";
2085         case LandmarkNavigationRole:
2086             return @"AXLandmarkNavigation";
2087         case LandmarkDocRegionRole:
2088         case LandmarkRegionRole:
2089             return @"AXLandmarkRegion";
2090         case LandmarkSearchRole:
2091             return @"AXLandmarkSearch";
2092         case ApplicationAlertRole:
2093             return @"AXApplicationAlert";
2094         case ApplicationAlertDialogRole:
2095             return @"AXApplicationAlertDialog";
2096         case ApplicationDialogRole:
2097             return @"AXApplicationDialog";
2098         case ApplicationGroupRole:
2099         case ApplicationTextGroupRole:
2100         case FeedRole:
2101         case FootnoteRole:
2102             return @"AXApplicationGroup";
2103         case ApplicationLogRole:
2104             return @"AXApplicationLog";
2105         case ApplicationMarqueeRole:
2106             return @"AXApplicationMarquee";
2107         case ApplicationStatusRole:
2108             return @"AXApplicationStatus";
2109         case ApplicationTimerRole:
2110             return @"AXApplicationTimer";
2111         case DocumentRole:
2112             return @"AXDocument";
2113         case DocumentArticleRole:
2114             return @"AXDocumentArticle";
2115         case DocumentMathRole:
2116             return @"AXDocumentMath";
2117         case DocumentNoteRole:
2118             return @"AXDocumentNote";
2119         case UserInterfaceTooltipRole:
2120             return @"AXUserInterfaceTooltip";
2121         case TabPanelRole:
2122             return @"AXTabPanel";
2123         case DefinitionRole:
2124             return @"AXDefinition";
2125         case DescriptionListTermRole:
2126         case TermRole:
2127             return @"AXTerm";
2128         case DescriptionListDetailRole:
2129             return @"AXDescription";
2130         case WebApplicationRole:
2131             return @"AXWebApplication";
2132             // Default doesn't return anything, so roles defined below can be chosen.
2133         default:
2134             break;
2135     }
2136     
2137     if (role == MathElementRole) {
2138         if (m_object->isMathFraction())
2139             return @"AXMathFraction";
2140         if (m_object->isMathFenced())
2141             return @"AXMathFenced";
2142         if (m_object->isMathSubscriptSuperscript())
2143             return @"AXMathSubscriptSuperscript";
2144         if (m_object->isMathRow())
2145             return @"AXMathRow";
2146         if (m_object->isMathUnderOver())
2147             return @"AXMathUnderOver";
2148         if (m_object->isMathSquareRoot())
2149             return @"AXMathSquareRoot";
2150         if (m_object->isMathRoot())
2151             return @"AXMathRoot";
2152         if (m_object->isMathText())
2153             return @"AXMathText";
2154         if (m_object->isMathNumber())
2155             return @"AXMathNumber";
2156         if (m_object->isMathIdentifier())
2157             return @"AXMathIdentifier";
2158         if (m_object->isMathTable())
2159             return @"AXMathTable";
2160         if (m_object->isMathTableRow())
2161             return @"AXMathTableRow";
2162         if (m_object->isMathTableCell())
2163             return @"AXMathTableCell";
2164         if (m_object->isMathFenceOperator())
2165             return @"AXMathFenceOperator";
2166         if (m_object->isMathSeparatorOperator())
2167             return @"AXMathSeparatorOperator";
2168         if (m_object->isMathOperator())
2169             return @"AXMathOperator";
2170         if (m_object->isMathMultiscript())
2171             return @"AXMathMultiscript";
2172     }
2173     
2174     if (role == VideoRole)
2175         return @"AXVideo";
2176     if (role == AudioRole)
2177         return @"AXAudio";
2178     if (role == DetailsRole)
2179         return @"AXDetails";
2180     if (role == SummaryRole)
2181         return @"AXSummary";
2182     if (role == TimeRole)
2183         return @"AXTimeGroup";
2184
2185     if (m_object->isMediaTimeline())
2186         return NSAccessibilityTimelineSubrole;
2187
2188     if (m_object->isSwitch())
2189         return NSAccessibilitySwitchSubrole;
2190
2191     if (m_object->isStyleFormatGroup()) {
2192         if (Node* node = m_object->node()) {
2193             if (node->hasTagName(kbdTag))
2194                 return @"AXKeyboardInputStyleGroup";
2195             if (node->hasTagName(codeTag))
2196                 return @"AXCodeStyleGroup";
2197             if (node->hasTagName(preTag))
2198                 return @"AXPreformattedStyleGroup";
2199             if (node->hasTagName(sampTag))
2200                 return @"AXSampleStyleGroup";
2201             if (node->hasTagName(varTag))
2202                 return @"AXVariableStyleGroup";
2203             if (node->hasTagName(citeTag))
2204                 return @"AXCiteStyleGroup";
2205             if (node->hasTagName(insTag))
2206                 return @"AXInsertStyleGroup";
2207             if (node->hasTagName(delTag))
2208                 return @"AXDeleteStyleGroup";
2209             if (node->hasTagName(supTag))
2210                 return @"AXSuperscriptStyleGroup";
2211             if (node->hasTagName(subTag))
2212                 return @"AXSubscriptStyleGroup";
2213         }
2214     }
2215     
2216     // Ruby subroles
2217     switch (role) {
2218     case RubyBaseRole:
2219         return NSAccessibilityRubyBaseSubrole;
2220     case RubyBlockRole:
2221         return NSAccessibilityRubyBlockSubrole;
2222     case RubyInlineRole:
2223         return NSAccessibilityRubyInlineSubrole;
2224     case RubyRunRole:
2225         return NSAccessibilityRubyRunSubrole;
2226     case RubyTextRole:
2227         return NSAccessibilityRubyTextSubrole;
2228     default:
2229         break;
2230     }
2231     
2232     return nil;
2233 }
2234 #pragma clang diagnostic pop
2235
2236 - (NSString*)roleDescription
2237 {
2238     if (!m_object)
2239         return nil;
2240
2241 #pragma clang diagnostic push
2242 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2243     // attachments have the AXImage role, but a different subrole
2244     if (m_object->isAttachment())
2245         return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute];
2246 #pragma clang diagnostic pop
2247
2248     const AtomicString& overrideRoleDescription = m_object->roleDescription();
2249     if (!overrideRoleDescription.isNull() && !overrideRoleDescription.isEmpty())
2250         return overrideRoleDescription;
2251     
2252     NSString* axRole = [self role];
2253     
2254     if ([axRole isEqualToString:NSAccessibilityGroupRole]) {
2255         
2256         if (m_object->isOutput())
2257             return AXOutputText();
2258         
2259         NSString *ariaLandmarkRoleDescription = [self ariaLandmarkRoleDescription];
2260         if (ariaLandmarkRoleDescription)
2261             return ariaLandmarkRoleDescription;
2262         
2263         switch (m_object->roleValue()) {
2264         case AudioRole:
2265             return localizedMediaControlElementString("AudioElement");
2266         case DefinitionRole:
2267             return AXDefinitionText();
2268         case DescriptionListTermRole:
2269         case TermRole:
2270             return AXDescriptionListTermText();
2271         case DescriptionListDetailRole:
2272             return AXDescriptionListDetailText();
2273         case DetailsRole:
2274             return AXDetailsText();
2275         case FeedRole:
2276             return AXFeedText();
2277         case FigureRole:
2278             return AXFigureText();
2279         case FooterRole:
2280             return AXFooterRoleDescriptionText();
2281         case MarkRole:
2282             return AXMarkText();
2283         case VideoRole:
2284             return localizedMediaControlElementString("VideoElement");
2285         default:
2286             return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, [self subrole]);
2287         }
2288     }
2289     
2290     if ([axRole isEqualToString:@"AXWebArea"])
2291         return AXWebAreaText();
2292     
2293     if ([axRole isEqualToString:@"AXLink"])
2294         return AXLinkText();
2295     
2296     if ([axRole isEqualToString:@"AXListMarker"])
2297         return AXListMarkerText();
2298     
2299     if ([axRole isEqualToString:@"AXImageMap"])
2300         return AXImageMapText();
2301     
2302     if ([axRole isEqualToString:@"AXHeading"])
2303         return AXHeadingText();
2304     
2305     if ([axRole isEqualToString:NSAccessibilityTextFieldRole]) {
2306         auto* node = m_object->node();
2307         if (is<HTMLInputElement>(node)) {
2308             auto& input = downcast<HTMLInputElement>(*node);
2309             if (input.isEmailField())
2310                 return AXEmailFieldText();
2311             if (input.isTelephoneField())
2312                 return AXTelephoneFieldText();
2313             if (input.isURLField())
2314                 return AXURLFieldText();
2315             if (input.isNumberField())
2316                 return AXNumberFieldText();
2317             
2318             // These input types are not enabled on mac yet, we check the type attribute for now.
2319             auto& type = input.attributeWithoutSynchronization(typeAttr);
2320             if (equalLettersIgnoringASCIICase(type, "date"))
2321                 return AXDateFieldText();
2322             if (equalLettersIgnoringASCIICase(type, "time"))
2323                 return AXTimeFieldText();
2324             if (equalLettersIgnoringASCIICase(type, "week"))
2325                 return AXWeekFieldText();
2326             if (equalLettersIgnoringASCIICase(type, "month"))
2327                 return AXMonthFieldText();
2328             if (equalLettersIgnoringASCIICase(type, "datetime-local"))
2329                 return AXDateTimeFieldText();
2330         }
2331     }
2332     
2333     if (m_object->isFileUploadButton())
2334         return AXFileUploadButtonText();
2335     
2336     // Only returning for DL (not UL or OL) because description changed with HTML5 from 'definition list' to
2337     // superset 'description list' and does not return the same values in AX API on some OS versions. 
2338     if (is<AccessibilityList>(*m_object)) {
2339         if (downcast<AccessibilityList>(*m_object).isDescriptionList())
2340             return AXDescriptionListText();
2341     }
2342     
2343     if (m_object->roleValue() == HorizontalRuleRole)
2344         return AXHorizontalRuleDescriptionText();
2345     
2346     // AppKit also returns AXTab for the role description for a tab item.
2347     if (m_object->isTabItem())
2348         return NSAccessibilityRoleDescription(@"AXTab", nil);
2349     
2350     if (m_object->isSummary())
2351         return AXSummaryText();
2352     
2353     // We should try the system default role description for all other roles.
2354     // If we get the same string back, then as a last resort, return unknown.
2355     NSString* defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]);
2356     
2357     // On earlier Mac versions (Lion), using a non-standard subrole would result in a role description
2358     // being returned that looked like AXRole:AXSubrole. To make all platforms have the same role descriptions
2359     // we should fallback on a role description ignoring the subrole in these cases.
2360     if ([defaultRoleDescription isEqualToString:[NSString stringWithFormat:@"%@:%@", axRole, [self subrole]]])
2361         defaultRoleDescription = NSAccessibilityRoleDescription(axRole, nil);
2362     
2363     if (![defaultRoleDescription isEqualToString:axRole])
2364         return defaultRoleDescription;
2365     
2366     return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);
2367 }
2368
2369 - (NSString *)computedRoleString
2370 {
2371     if (!m_object)
2372         return nil;
2373     return m_object->computedRoleString();
2374 }
2375
2376 - (id)scrollViewParent
2377 {
2378     if (!is<AccessibilityScrollView>(m_object))
2379         return nil;
2380     
2381     // If this scroll view provides it's parent object (because it's a sub-frame), then
2382     // we should not find the remoteAccessibilityParent.
2383     if (m_object->parentObject())
2384         return nil;
2385     
2386     ScrollView* scroll = downcast<AccessibilityScrollView>(*m_object).scrollView();
2387     if (!scroll)
2388         return nil;
2389     
2390     if (scroll->platformWidget())
2391         return NSAccessibilityUnignoredAncestor(scroll->platformWidget());
2392     
2393     return [self remoteAccessibilityParentObject];
2394 }
2395
2396 - (NSString *)valueDescriptionForMeter
2397 {
2398     if (!m_object)
2399         return nil;
2400     
2401     String valueDescription = m_object->valueDescription();
2402 #if ENABLE(METER_ELEMENT)
2403     if (!is<AccessibilityProgressIndicator>(m_object))
2404         return valueDescription;
2405     auto &meter = downcast<AccessibilityProgressIndicator>(*m_object);
2406     String gaugeRegionValue = meter.gaugeRegionValueDescription();
2407     if (!gaugeRegionValue.isEmpty()) {
2408         StringBuilder builder;
2409         builder.append(valueDescription);
2410         if (builder.length())
2411             builder.appendLiteral(", ");
2412         builder.append(gaugeRegionValue);
2413         return builder.toString();
2414     }
2415 #endif
2416     return valueDescription;
2417 }
2418
2419 // FIXME: split up this function in a better way.
2420 // suggestions: Use a hash table that maps attribute names to function calls,
2421 // or maybe pointers to member functions
2422 - (id)accessibilityAttributeValue:(NSString*)attributeName
2423 {
2424     if (![self updateObjectBackingStore])
2425         return nil;
2426     
2427     if (m_object->isDetachedFromParent())
2428         return nil;
2429     
2430     if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])
2431         return [self role];
2432     
2433     if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute])
2434         return [self subrole];
2435     
2436     if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])
2437         return [self roleDescription];
2438
2439     // AXARIARole is only used by DumpRenderTree (so far).
2440     if ([attributeName isEqualToString:@"AXARIARole"])
2441         return [self computedRoleString];
2442     
2443     if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {
2444         
2445         // This will return the parent of the AXWebArea, if this is a web area.
2446         id scrollViewParent = [self scrollViewParent];
2447         if (scrollViewParent)
2448             return scrollViewParent;
2449         
2450         // Tree item (changed to AXRows) can only report the tree (AXOutline) as its parent.
2451         if (m_object->isTreeItem()) {
2452             AccessibilityObject* parent = m_object->parentObjectUnignored();
2453             while (parent) {
2454                 if (parent->isTree())
2455                     return parent->wrapper();
2456                 parent = parent->parentObjectUnignored();
2457             }
2458         }
2459         
2460         AccessibilityObject* parent = m_object->parentObjectUnignored();
2461         if (!parent)
2462             return nil;
2463         
2464         // In WebKit1, the scroll view is provided by the system (the attachment view), so the parent
2465         // should be reported directly as such.
2466         if (m_object->isWebArea() && parent->isAttachment())
2467             return [parent->wrapper() attachmentView];
2468         
2469         return parent->wrapper();
2470     }
2471     
2472     if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) {
2473         if (m_object->children().isEmpty()) {
2474             NSArray* children = [self renderWidgetChildren];
2475             if (children != nil)
2476                 return children;
2477         }
2478         
2479         // The tree's (AXOutline) children are supposed to be its rows and columns.
2480         // The ARIA spec doesn't have columns, so we just need rows.
2481         if (m_object->isTree())
2482             return [self accessibilityAttributeValue:NSAccessibilityRowsAttribute];
2483         
2484         // A tree item should only expose its content as its children (not its rows)
2485         if (m_object->isTreeItem()) {
2486             AccessibilityObject::AccessibilityChildrenVector contentCopy;
2487             m_object->ariaTreeItemContent(contentCopy);
2488             return convertToNSArray(contentCopy);
2489         }
2490         
2491         return convertToNSArray(m_object->children());
2492     }
2493     
2494     if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
2495         if (m_object->canHaveSelectedChildren()) {
2496             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2497             m_object->selectedChildren(selectedChildrenCopy);
2498             return convertToNSArray(selectedChildrenCopy);
2499         }
2500         return nil;
2501     }
2502     
2503     if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) {
2504         if (m_object->isListBox()) {
2505             AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy;
2506             m_object->visibleChildren(visibleChildrenCopy);
2507             return convertToNSArray(visibleChildrenCopy);
2508         }
2509         else if (m_object->isList())
2510             return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
2511         
2512         return nil;
2513     }
2514     
2515     
2516     if (m_object->isWebArea()) {
2517         if ([attributeName isEqualToString:@"AXLinkUIElements"]) {
2518             AccessibilityObject::AccessibilityChildrenVector links;
2519             downcast<AccessibilityRenderObject>(*m_object).getDocumentLinks(links);
2520             return convertToNSArray(links);
2521         }
2522         if ([attributeName isEqualToString:@"AXLoaded"])
2523             return [NSNumber numberWithBool:m_object->isLoaded()];
2524         if ([attributeName isEqualToString:@"AXLayoutCount"])
2525             return [NSNumber numberWithInt:m_object->layoutCount()];
2526         if ([attributeName isEqualToString:NSAccessibilityLoadingProgressAttribute])
2527             return [NSNumber numberWithDouble:m_object->estimatedLoadingProgress()];
2528     }
2529     
2530     if (m_object->isTextControl()) {
2531         if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) {
2532             int length = m_object->textLength();
2533             if (length < 0)
2534                 return nil;
2535             return [NSNumber numberWithUnsignedInt:length];
2536         }
2537         if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
2538             String selectedText = m_object->selectedText();
2539             if (selectedText.isNull())
2540                 return nil;
2541             return (NSString*)selectedText;
2542         }
2543         if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
2544             PlainTextRange textRange = m_object->selectedTextRange();
2545             if (textRange.isNull())
2546                 return [NSValue valueWithRange:NSMakeRange(0, 0)];
2547             return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)];
2548         }
2549         // TODO: Get actual visible range. <rdar://problem/4712101>
2550         if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
2551             return m_object->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, m_object->textLength())];
2552         if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) {
2553             // if selectionEnd > 0, then there is selected text and this question should not be answered
2554             if (m_object->isPasswordField() || m_object->selectionEnd() > 0)
2555                 return nil;
2556             
2557             AccessibilityObject* focusedObject = m_object->focusedUIElement();
2558             if (focusedObject != m_object)
2559                 return nil;
2560             
2561             VisiblePosition focusedPosition = focusedObject->visiblePositionForIndex(focusedObject->selectionStart(), true);
2562             int lineNumber = m_object->lineForPosition(focusedPosition);
2563             if (lineNumber < 0)
2564                 return nil;
2565             
2566             return [NSNumber numberWithInt:lineNumber];
2567         }
2568     }
2569     
2570     if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {
2571         URL url = m_object->url();
2572         if (url.isNull())
2573             return nil;
2574         return (NSURL*)url;
2575     }
2576
2577     // Only native spin buttons have increment and decrement buttons.
2578     if (is<AccessibilitySpinButton>(*m_object)) {
2579         if ([attributeName isEqualToString:NSAccessibilityIncrementButtonAttribute])
2580             return downcast<AccessibilitySpinButton>(*m_object).incrementButton()->wrapper();
2581         if ([attributeName isEqualToString:NSAccessibilityDecrementButtonAttribute])
2582             return downcast<AccessibilitySpinButton>(*m_object).decrementButton()->wrapper();
2583     }
2584     
2585     if ([attributeName isEqualToString: @"AXVisited"])
2586         return [NSNumber numberWithBool: m_object->isVisited()];
2587     
2588     if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) {
2589         if (m_object->isAttachment()) {
2590             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute])
2591                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute];
2592         }
2593         
2594         // Meter elements should communicate their content via AXValueDescription.
2595         if (m_object->isMeter())
2596             return [NSString string];
2597         
2598         // Summary element should use its text node as AXTitle.
2599         if (m_object->isSummary())
2600             return m_object->textUnderElement();
2601         
2602         return [self baseAccessibilityTitle];
2603     }
2604     
2605     if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) {
2606         if (m_object->isAttachment()) {
2607             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute])
2608                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute];
2609         }
2610         return [self baseAccessibilityDescription];
2611     }
2612     
2613     if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
2614         if (m_object->isAttachment()) {
2615             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute])
2616                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute];
2617         }
2618         if (m_object->supportsRangeValue())
2619             return [NSNumber numberWithFloat:m_object->valueForRange()];
2620         if (m_object->roleValue() == SliderThumbRole)
2621             return [NSNumber numberWithFloat:m_object->parentObject()->valueForRange()];
2622         if (m_object->isHeading())
2623             return [NSNumber numberWithInt:m_object->headingLevel()];
2624         
2625         if (m_object->isCheckboxOrRadio() || m_object->isMenuItem() || m_object->isSwitch() || m_object->isToggleButton()) {
2626             switch (m_object->checkboxOrRadioValue()) {
2627                 case ButtonStateOff:
2628                     return [NSNumber numberWithInt:0];
2629                 case ButtonStateOn:
2630                     return [NSNumber numberWithInt:1];
2631                 case ButtonStateMixed:
2632                     return [NSNumber numberWithInt:2];
2633             }
2634         }
2635         
2636         // radio groups return the selected radio button as the AXValue
2637         if (m_object->isRadioGroup()) {
2638             AccessibilityObject* radioButton = m_object->selectedRadioButton();
2639             if (!radioButton)
2640                 return nil;
2641             return radioButton->wrapper();
2642         }
2643         
2644         if (m_object->isTabList()) {
2645             AccessibilityObject* tabItem = m_object->selectedTabItem();
2646             if (!tabItem)
2647                 return nil;
2648             return tabItem->wrapper();
2649         }
2650         
2651         if (m_object->isTabItem())
2652             return [NSNumber numberWithInt:m_object->isSelected()];
2653         
2654         if (m_object->isColorWell()) {
2655             int r, g, b;
2656             m_object->colorValue(r, g, b);
2657             return [NSString stringWithFormat:@"rgb %7.5f %7.5f %7.5f 1", r / 255., g / 255., b / 255.];
2658         }
2659         
2660         return m_object->stringValue();
2661     }
2662
2663     if ([attributeName isEqualToString:(NSString *)kAXMenuItemMarkCharAttribute]) {
2664         const unichar ch = 0x2713; // ✓ used on Mac for selected menu items.
2665         return (m_object->isChecked()) ? [NSString stringWithCharacters:&ch length:1] : nil;
2666     }
2667     
2668     if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute]) {
2669         // Indeterminate progress indicator should return 0.
2670         if (m_object->ariaRoleAttribute() == ProgressIndicatorRole && !m_object->hasAttribute(aria_valuenowAttr))
2671             return @0;
2672         return [NSNumber numberWithFloat:m_object->minValueForRange()];
2673     }
2674     
2675     if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute]) {
2676         // Indeterminate progress indicator should return 0.
2677         if (m_object->ariaRoleAttribute() == ProgressIndicatorRole && !m_object->hasAttribute(aria_valuenowAttr))
2678             return @0;
2679         return [NSNumber numberWithFloat:m_object->maxValueForRange()];
2680     }
2681     
2682     if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])
2683         return [self baseAccessibilityHelpText];
2684     
2685     if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2686         return [NSNumber numberWithBool: m_object->isFocused()];
2687     
2688     if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])
2689         return [NSNumber numberWithBool: m_object->isEnabled()];
2690     
2691     if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) {
2692         IntSize s = snappedIntRect(m_object->elementRect()).size();
2693         return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())];
2694     }
2695     
2696     if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])
2697         return [self position];
2698     if ([attributeName isEqualToString:NSAccessibilityPathAttribute])
2699         return [self path];
2700     
2701     if ([attributeName isEqualToString: NSAccessibilityWindowAttribute] ||
2702         [attributeName isEqualToString: NSAccessibilityTopLevelUIElementAttribute]) {
2703         
2704         id remoteParent = [self remoteAccessibilityParentObject];
2705         if (remoteParent)
2706             return [remoteParent accessibilityAttributeValue:attributeName];
2707         
2708         FrameView* fv = m_object->documentFrameView();
2709         if (fv)
2710             return [fv->platformWidget() window];
2711         return nil;
2712     }
2713     
2714     if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) {
2715         AtomicString accessKey = m_object->accessKey();
2716         if (accessKey.isNull())
2717             return nil;
2718         return accessKey;
2719     }
2720     
2721     if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) {
2722         if (m_object->isTabList()) {
2723             AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2724             m_object->tabChildren(tabsChildren);
2725             return convertToNSArray(tabsChildren);
2726         }
2727     }
2728     
2729     if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) {
2730         // The contents of a tab list are all the children except the tabs.
2731         if (m_object->isTabList()) {
2732             const auto& children = m_object->children();
2733             AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2734             m_object->tabChildren(tabsChildren);
2735             
2736             AccessibilityObject::AccessibilityChildrenVector contents;
2737             unsigned childrenSize = children.size();
2738             for (unsigned k = 0; k < childrenSize; ++k) {
2739                 if (tabsChildren.find(children[k]) == WTF::notFound)
2740                     contents.append(children[k]);
2741             }
2742             return convertToNSArray(contents);
2743         } else if (m_object->isScrollView()) {
2744             // A scrollView's contents are everything except the scroll bars.
2745             AccessibilityObject::AccessibilityChildrenVector contents;
2746             for (const auto& child : m_object->children()) {
2747                 if (!child->isScrollbar())
2748                     contents.append(child);
2749             }
2750             return convertToNSArray(contents);
2751         }
2752     }
2753     
2754     if (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility()) {
2755         auto& table = downcast<AccessibilityTable>(*m_object);
2756         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute])
2757             return convertToNSArray(table.rows());
2758         
2759         if ([attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2760             AccessibilityObject::AccessibilityChildrenVector visibleRows;
2761             table.visibleRows(visibleRows);
2762             return convertToNSArray(visibleRows);
2763         }
2764         
2765         // TODO: distinguish between visible and non-visible columns
2766         if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute] ||
2767             [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute]) {
2768             return convertToNSArray(table.columns());
2769         }
2770         
2771         if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2772             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2773             m_object->selectedChildren(selectedChildrenCopy);
2774             return convertToNSArray(selectedChildrenCopy);
2775         }
2776         
2777         // HTML tables don't support these
2778         if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute] ||
2779             [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute])
2780             return nil;
2781         
2782         if ([attributeName isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
2783             AccessibilityObject::AccessibilityChildrenVector columnHeaders;
2784             table.columnHeaders(columnHeaders);
2785             return convertToNSArray(columnHeaders);
2786         }
2787         
2788         if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2789             AccessibilityObject* headerContainer = table.headerContainer();
2790             if (headerContainer)
2791                 return headerContainer->wrapper();
2792             return nil;
2793         }
2794         
2795         if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
2796             AccessibilityObject::AccessibilityChildrenVector rowHeaders;
2797             table.rowHeaders(rowHeaders);
2798             return convertToNSArray(rowHeaders);
2799         }
2800         
2801         if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute]) {
2802             AccessibilityObject::AccessibilityChildrenVector cells;
2803             table.cells(cells);
2804             return convertToNSArray(cells);
2805         }
2806         
2807         if ([attributeName isEqualToString:NSAccessibilityColumnCountAttribute])
2808             return @(table.columnCount());
2809         
2810         if ([attributeName isEqualToString:NSAccessibilityRowCountAttribute])
2811             return @(table.rowCount());
2812         
2813         if ([attributeName isEqualToString:NSAccessibilityARIAColumnCountAttribute])
2814             return @(table.ariaColumnCount());
2815         
2816         if ([attributeName isEqualToString:NSAccessibilityARIARowCountAttribute])
2817             return @(table.ariaRowCount());
2818     }
2819     
2820     if (is<AccessibilityTableColumn>(*m_object)) {
2821         auto& column = downcast<AccessibilityTableColumn>(*m_object);
2822         if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2823             return [NSNumber numberWithInt:column.columnIndex()];
2824         
2825         // rows attribute for a column is the list of all the elements in that column at each row
2826         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] ||
2827             [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2828             return convertToNSArray(column.children());
2829         }
2830         if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2831             AccessibilityObject* header = column.headerObject();
2832             if (!header)
2833                 return nil;
2834             return header->wrapper();
2835         }
2836     }
2837     
2838     if (is<AccessibilityTableCell>(*m_object)) {
2839         auto& cell = downcast<AccessibilityTableCell>(*m_object);
2840         if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) {
2841             std::pair<unsigned, unsigned> rowRange;
2842             cell.rowIndexRange(rowRange);
2843             return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)];
2844         }
2845         if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) {
2846             std::pair<unsigned, unsigned> columnRange;
2847             cell.columnIndexRange(columnRange);
2848             return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)];
2849         }
2850         if ([attributeName isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute]) {
2851             AccessibilityObject::AccessibilityChildrenVector columnHeaders;
2852             cell.columnHeaders(columnHeaders);
2853             return convertToNSArray(columnHeaders);
2854         }
2855         if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
2856             AccessibilityObject::AccessibilityChildrenVector rowHeaders;
2857             cell.rowHeaders(rowHeaders);
2858             return convertToNSArray(rowHeaders);
2859         }
2860         if ([attributeName isEqualToString:NSAccessibilityARIAColumnIndexAttribute])
2861             return @(cell.ariaColumnIndex());
2862         
2863         if ([attributeName isEqualToString:NSAccessibilityARIARowIndexAttribute])
2864             return @(cell.ariaRowIndex());
2865     }
2866     
2867     if (m_object->isTree()) {
2868         if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2869             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2870             m_object->selectedChildren(selectedChildrenCopy);
2871             return convertToNSArray(selectedChildrenCopy);
2872         }
2873         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) {
2874             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2875             m_object->ariaTreeRows(rowsCopy);
2876             return convertToNSArray(rowsCopy);
2877         }
2878         
2879         // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least.
2880         if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute])
2881             return [NSArray array];
2882     }
2883     
2884     if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) {
2885         if (m_object->isTreeItem()) {
2886             AccessibilityObject* parent = m_object->parentObject();
2887             for (; parent && !parent->isTree(); parent = parent->parentObject())
2888             { }
2889             
2890             if (!parent)
2891                 return nil;
2892             
2893             // Find the index of this item by iterating the parents.
2894             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2895             parent->ariaTreeRows(rowsCopy);
2896             size_t count = rowsCopy.size();
2897             for (size_t k = 0; k < count; ++k)
2898                 if (rowsCopy[k]->wrapper() == self)
2899                     return [NSNumber numberWithUnsignedInt:k];
2900             
2901             return nil;
2902         }
2903         if (is<AccessibilityTableRow>(*m_object)) {
2904             if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2905                 return [NSNumber numberWithInt:downcast<AccessibilityTableRow>(*m_object).rowIndex()];
2906         }
2907     }
2908     
2909     // The rows that are considered inside this row.
2910     if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) {
2911         if (m_object->isTreeItem()) {
2912             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2913             m_object->ariaTreeItemDisclosedRows(rowsCopy);
2914             return convertToNSArray(rowsCopy);
2915         } else if (is<AccessibilityARIAGridRow>(*m_object)) {
2916             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2917             downcast<AccessibilityARIAGridRow>(*m_object).disclosedRows(rowsCopy);
2918             return convertToNSArray(rowsCopy);
2919         }
2920     }
2921     
2922     // The row that contains this row. It should be the same as the first parent that is a treeitem.
2923     if ([attributeName isEqualToString:NSAccessibilityDisclosedByRowAttribute]) {
2924         if (m_object->isTreeItem()) {
2925             AccessibilityObject* parent = m_object->parentObject();
2926             while (parent) {
2927                 if (parent->isTreeItem())
2928                     return parent->wrapper();
2929                 // If the parent is the tree itself, then this value == nil.
2930                 if (parent->isTree())
2931                     return nil;
2932                 parent = parent->parentObject();
2933             }
2934             return nil;
2935         } else if (is<AccessibilityARIAGridRow>(*m_object)) {
2936             AccessibilityObject* row = downcast<AccessibilityARIAGridRow>(*m_object).disclosedByRow();
2937             if (!row)
2938                 return nil;
2939             return row->wrapper();
2940         }
2941     }
2942     
2943     if ([attributeName isEqualToString:NSAccessibilityDisclosureLevelAttribute]) {
2944         // Convert from 1-based level (from aria-level spec) to 0-based level (Mac)
2945         int level = m_object->hierarchicalLevel();
2946         if (level > 0)
2947             level -= 1;
2948         return [NSNumber numberWithInt:level];
2949     }
2950     if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2951         return [NSNumber numberWithBool:m_object->isExpanded()];
2952     
2953     if (m_object->isList() && [attributeName isEqualToString:NSAccessibilityOrientationAttribute])
2954         return NSAccessibilityVerticalOrientationValue;
2955     
2956     if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2957         return [self textMarkerRangeForSelection];
2958     
2959     if (m_object->renderer()) {
2960         if ([attributeName isEqualToString: @"AXStartTextMarker"])
2961             return [self textMarkerForVisiblePosition:startOfDocument(&m_object->renderer()->document())];
2962         if ([attributeName isEqualToString: @"AXEndTextMarker"])
2963             return [self textMarkerForVisiblePosition:endOfDocument(&m_object->renderer()->document())];
2964     }
2965     
2966     if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])
2967         return [NSNumber numberWithUnsignedInt:m_object->blockquoteLevel()];
2968     if ([attributeName isEqualToString:@"AXTableLevel"])
2969         return [NSNumber numberWithInt:m_object->tableLevel()];
2970     
2971     if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) {
2972         AccessibilityObject::AccessibilityChildrenVector linkedUIElements;
2973         m_object->linkedUIElements(linkedUIElements);
2974         return convertToNSArray(linkedUIElements);
2975     }
2976     
2977     if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2978         return [NSNumber numberWithBool:m_object->isSelected()];
2979     
2980     if ([attributeName isEqualToString: NSAccessibilityARIACurrentAttribute])
2981         return m_object->ariaCurrentValue();
2982     
2983     if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && m_object->isMenuButton()) {
2984         AccessibilityObject* uiElement = downcast<AccessibilityRenderObject>(*m_object).menuForMenuButton();
2985         if (uiElement)
2986             return [NSArray arrayWithObject:uiElement->wrapper()];
2987     }
2988     
2989     if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
2990         if (!m_object->exposesTitleUIElement())
2991             return nil;
2992         
2993         AccessibilityObject* obj = m_object->titleUIElement();
2994         if (obj)
2995             return obj->wrapper();
2996         return nil;
2997     }
2998     
2999     if ([attributeName isEqualToString:NSAccessibilityValueDescriptionAttribute]) {
3000         if (m_object->isMeter())
3001             return [self valueDescriptionForMeter];
3002         return m_object->valueDescription();
3003     }
3004     
3005     if ([attributeName isEqualToString:NSAccessibilityOrientationAttribute]) {
3006         AccessibilityOrientation elementOrientation = m_object->orientation();
3007         if (elementOrientation == AccessibilityOrientationVertical)
3008             return NSAccessibilityVerticalOrientationValue;
3009         if (elementOrientation == AccessibilityOrientationHorizontal)
3010             return NSAccessibilityHorizontalOrientationValue;
3011         if (elementOrientation == AccessibilityOrientationUndefined)
3012             return NSAccessibilityUnknownOrientationValue;
3013         return nil;
3014     }
3015     
3016     if ([attributeName isEqualToString:NSAccessibilityHorizontalScrollBarAttribute]) {
3017         AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationHorizontal);
3018         if (scrollBar)
3019             return scrollBar->wrapper();
3020         return nil;
3021     }
3022     if ([attributeName isEqualToString:NSAccessibilityVerticalScrollBarAttribute]) {
3023         AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationVertical);
3024         if (scrollBar)
3025             return scrollBar->wrapper();
3026         return nil;
3027     }
3028     
3029     if ([attributeName isEqualToString:NSAccessibilitySortDirectionAttribute]) {
3030         switch (m_object->sortDirection()) {
3031             case SortDirectionAscending:
3032                 return NSAccessibilityAscendingSortDirectionValue;
3033             case SortDirectionDescending:
3034                 return NSAccessibilityDescendingSortDirectionValue;
3035             default:
3036                 return NSAccessibilityUnknownSortDirectionValue;
3037         }
3038     }
3039     
3040     if ([attributeName isEqualToString:NSAccessibilityLanguageAttribute])
3041         return m_object->language();
3042     
3043     if ([attributeName isEqualToString:NSAccessibilityExpandedAttribute])
3044         return [NSNumber numberWithBool:m_object->isExpanded()];
3045     
3046     if ([attributeName isEqualToString:NSAccessibilityRequiredAttribute])
3047         return [NSNumber numberWithBool:m_object->isRequired()];
3048     
3049     if ([attributeName isEqualToString:NSAccessibilityInvalidAttribute])
3050         return m_object->invalidStatus();
3051     
3052     if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) {
3053         AccessibilityObject::AccessibilityChildrenVector ariaOwns;
3054         m_object->ariaOwnsElements(ariaOwns);
3055         return convertToNSArray(ariaOwns);
3056     }
3057     
3058     if ([attributeName isEqualToString:NSAccessibilityARIAPosInSetAttribute])
3059         return [NSNumber numberWithInt:m_object->ariaPosInSet()];
3060     if ([attributeName isEqualToString:NSAccessibilityARIASetSizeAttribute])
3061         return [NSNumber numberWithInt:m_object->ariaSetSize()];
3062     
3063     if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
3064         return [NSNumber numberWithBool:m_object->isARIAGrabbed()];
3065     
3066     if ([attributeName isEqualToString:NSAccessibilityDropEffectsAttribute]) {
3067         Vector<String> dropEffects;
3068         m_object->determineARIADropEffects(dropEffects);
3069         return convertStringsToNSArray(dropEffects);
3070     }
3071     
3072     if ([attributeName isEqualToString:NSAccessibilityPlaceholderValueAttribute])
3073         return m_object->placeholderValue();
3074
3075     if ([attributeName isEqualToString:NSAccessibilityValueAutofillAvailableAttribute])
3076         return @(m_object->isValueAutofillAvailable());
3077     
3078     if ([attributeName isEqualToString:NSAccessibilityValueAutofillTypeAttribute]) {
3079         switch (m_object->valueAutofillButtonType()) {
3080         case AutoFillButtonType::None:
3081             return @"none";
3082         case AutoFillButtonType::Credentials:
3083             return @"credentials";
3084         case AutoFillButtonType::Contacts:
3085             return @"contacts";
3086         }
3087     }
3088     
3089     if ([attributeName isEqualToString:NSAccessibilityValueAutofilledAttribute])
3090         return @(m_object->isValueAutofilled());
3091
3092     if ([attributeName isEqualToString:NSAccessibilityHasPopupAttribute])
3093         return [NSNumber numberWithBool:m_object->ariaHasPopup()];
3094
3095     if ([attributeName isEqualToString:NSAccessibilityDatetimeValueAttribute])
3096         return m_object->datetimeAttributeValue();
3097     
3098     if ([attributeName isEqualToString:NSAccessibilityInlineTextAttribute])
3099         return @(m_object->renderer() && is<RenderInline>(m_object->renderer()));
3100     
3101     // ARIA Live region attributes.
3102     if ([attributeName isEqualToString:NSAccessibilityARIALiveAttribute])
3103         return m_object->ariaLiveRegionStatus();
3104     if ([attributeName isEqualToString:NSAccessibilityARIARelevantAttribute])
3105         return m_object->ariaLiveRegionRelevant();
3106     if ([attributeName isEqualToString:NSAccessibilityARIAAtomicAttribute])
3107         return [NSNumber numberWithBool:m_object->ariaLiveRegionAtomic()];
3108     if ([attributeName isEqualToString:NSAccessibilityElementBusyAttribute])
3109         return [NSNumber numberWithBool:m_object->isBusy()];
3110     
3111     // MathML Attributes.
3112     if (m_object->isMathElement()) {
3113         if ([attributeName isEqualToString:NSAccessibilityMathRootIndexAttribute])
3114             return (m_object->mathRootIndexObject()) ? m_object->mathRootIndexObject()->wrapper() : 0;
3115         if ([attributeName isEqualToString:NSAccessibilityMathRootRadicandAttribute])
3116             return (m_object->mathRadicandObject()) ? m_object->mathRadicandObject()->wrapper() : 0;
3117         if ([attributeName isEqualToString:NSAccessibilityMathFractionNumeratorAttribute])
3118             return (m_object->mathNumeratorObject()) ? m_object->mathNumeratorObject()->wrapper() : 0;
3119         if ([attributeName isEqualToString:NSAccessibilityMathFractionDenominatorAttribute])
3120             return (m_object->mathDenominatorObject()) ? m_object->mathDenominatorObject()->wrapper() : 0;
3121         if ([attributeName isEqualToString:NSAccessibilityMathBaseAttribute])
3122             return (m_object->mathBaseObject()) ? m_object->mathBaseObject()->wrapper() : 0;
3123         if ([attributeName isEqualToString:NSAccessibilityMathSubscriptAttribute])
3124             return (m_object->mathSubscriptObject()) ? m_object->mathSubscriptObject()->wrapper() : 0;
3125         if ([attributeName isEqualToString:NSAccessibilityMathSuperscriptAttribute])
3126             return (m_object->mathSuperscriptObject()) ? m_object->mathSuperscriptObject()->wrapper() : 0;
3127         if ([attributeName isEqualToString:NSAccessibilityMathUnderAttribute])
3128             return (m_object->mathUnderObject()) ? m_object->mathUnderObject()->wrapper() : 0;
3129         if ([attributeName isEqualToString:NSAccessibilityMathOverAttribute])
3130             return (m_object->mathOverObject()) ? m_object->mathOverObject()->wrapper() : 0;
3131         if ([attributeName isEqualToString:NSAccessibilityMathFencedOpenAttribute])
3132             return m_object->mathFencedOpenString();
3133         if ([attributeName isEqualToString:NSAccessibilityMathFencedCloseAttribute])
3134             return m_object->mathFencedCloseString();
3135         if ([attributeName isEqualToString:NSAccessibilityMathLineThicknessAttribute])
3136             return [NSNumber numberWithInteger:m_object->mathLineThickness()];
3137         if ([attributeName isEqualToString:NSAccessibilityMathPostscriptsAttribute])
3138             return [self accessibilityMathPostscriptPairs];
3139         if ([attributeName isEqualToString:NSAccessibilityMathPrescriptsAttribute])
3140             return [self accessibilityMathPrescriptPairs];
3141     }
3142     
3143     if ([attributeName isEqualToString:NSAccessibilityExpandedTextValueAttribute])
3144         return m_object->expandedTextValue();
3145     
3146     if ([attributeName isEqualToString:NSAccessibilityDOMIdentifierAttribute])
3147         return m_object->identifierAttribute();
3148     if ([attributeName isEqualToString:NSAccessibilityDOMClassListAttribute]) {
3149         Vector<String> classList;
3150         m_object->classList(classList);
3151         return convertStringsToNSArray(classList);
3152     }
3153     
3154     // This allows us to connect to a plugin that creates a shadow node for editing (like PDFs).
3155     if ([attributeName isEqualToString:@"_AXAssociatedPluginParent"])
3156         return [self associatedPluginParent];
3157     
3158     // this is used only by DumpRenderTree for testing
3159     if ([attributeName isEqualToString:@"AXClickPoint"])
3160         return [NSValue valueWithPoint:m_object->clickPoint()];
3161     
3162     // This is used by DRT to verify CSS3 speech works.
3163     if ([attributeName isEqualToString:@"AXDRTSpeechAttribute"]) {
3164         ESpeak speakProperty = m_object->speakProperty();
3165         switch (speakProperty) {
3166             case SpeakNone:
3167                 return @"none";
3168             case SpeakSpellOut:
3169                 return @"spell-out";
3170             case SpeakDigits:
3171                 return @"digits";
3172             case SpeakLiteralPunctuation:
3173                 return @"literal-punctuation";
3174             case SpeakNoPunctuation:
3175                 return @"no-punctuation";
3176             default:
3177             case SpeakNormal:
3178                 return @"normal";
3179         }
3180     }
3181     
3182     // Used by DRT to find an accessible node by its element id.
3183     if ([attributeName isEqualToString:@"AXDRTElementIdAttribute"])
3184         return m_object->getAttribute(idAttr);
3185     
3186     if (m_object->isWebArea() && [attributeName isEqualToString:NSAccessibilityPreventKeyboardDOMEventDispatchAttribute])
3187         return [NSNumber numberWithBool:m_object->preventKeyboardDOMEventDispatch()];
3188     
3189     if (m_object->isWebArea() && [attributeName isEqualToString:NSAccessibilityCaretBrowsingEnabledAttribute])
3190         return [NSNumber numberWithBool:m_object->caretBrowsingEnabled()];
3191     
3192     // Multi-selectable
3193     if ([attributeName isEqualToString:NSAccessibilityIsMultiSelectableAttribute])
3194         return [NSNumber numberWithBool:m_object->isMultiSelectable()];
3195     
3196     // Document attributes
3197     if ([attributeName isEqualToString:NSAccessibilityDocumentURIAttribute]) {
3198         if (Document* document = m_object->document())
3199             return document->documentURI();
3200         return nil;
3201     }
3202     
3203     if ([attributeName isEqualToString:NSAccessibilityDocumentEncodingAttribute]) {
3204         if (Document* document = m_object->document())
3205             return document->encoding();
3206         return nil;
3207     }
3208     
3209     // Aria controls element
3210     if ([attributeName isEqualToString:NSAccessibilityAriaControlsAttribute]) {
3211         AccessibilityObject::AccessibilityChildrenVector ariaControls;
3212         m_object->ariaControlsElements(ariaControls);
3213         return convertToNSArray(ariaControls);
3214     }
3215
3216     if ([attributeName isEqualToString:NSAccessibilityFocusableAncestorAttribute]) {
3217         AccessibilityObject* object = m_object->focusableAncestor();
3218         return object ? object->wrapper() : nil;
3219     }
3220
3221     if ([attributeName isEqualToString:NSAccessibilityEditableAncestorAttribute]) {
3222         AccessibilityObject* object = m_object->editableAncestor();
3223         return object ? object->wrapper() : nil;
3224     }
3225
3226     if ([attributeName isEqualToString:NSAccessibilityHighestEditableAncestorAttribute]) {
3227         AccessibilityObject* object = m_object->highestEditableAncestor();
3228         return object ? object->wrapper() : nil;
3229     }
3230
3231     return nil;
3232 }
3233
3234 - (NSString *)accessibilityPlatformMathSubscriptKey
3235 {
3236     return NSAccessibilityMathSubscriptAttribute;
3237 }
3238
3239 - (NSString *)accessibilityPlatformMathSuperscriptKey
3240 {
3241     return NSAccessibilityMathSuperscriptAttribute;
3242 }
3243
3244 - (id)accessibilityFocusedUIElement
3245 {
3246     if (![self updateObjectBackingStore])
3247         return nil;
3248     
3249     RefPtr<AccessibilityObject> focusedObj = m_object->focusedUIElement();
3250     
3251     if (!focusedObj)
3252         return nil;
3253     
3254     return focusedObj->wrapper();
3255 }
3256
3257 - (id)accessibilityHitTest:(NSPoint)point
3258 {
3259     if (![self updateObjectBackingStore])
3260         return nil;
3261     
3262     m_object->updateChildrenIfNecessary();
3263     RefPtr<AccessibilityObject> axObject = m_object->accessibilityHitTest(IntPoint(point));
3264     if (axObject)
3265         return NSAccessibilityUnignoredAncestor(axObject->wrapper());
3266     return NSAccessibilityUnignoredAncestor(self);
3267 }
3268
3269 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName
3270 {
3271     if (![self updateObjectBackingStore])
3272         return NO;
3273     
3274     if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
3275         return YES;
3276     
3277     if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
3278         return m_object->canSetFocusAttribute();
3279     
3280     if ([attributeName isEqualToString: NSAccessibilityValueAttribute])
3281         return m_object->canSetValueAttribute();
3282     
3283     if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
3284         return m_object->canSetSelectedAttribute();
3285     
3286     if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute])
3287         return m_object->canSetSelectedChildrenAttribute();
3288     
3289     if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute]
3290         || [attributeName isEqualToString:NSAccessibilityExpandedAttribute])
3291         return m_object->canSetExpandedAttribute();
3292     
3293     if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute])
3294         return YES;
3295     
3296     if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute] ||
3297         [attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute] ||
3298         [attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
3299         return m_object->canSetTextRangeAttributes();
3300     
3301     if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
3302         return YES;
3303     
3304     if (m_object->isWebArea() && [attributeName isEqualToString:NSAccessibilityPreventKeyboardDOMEventDispatchAttribute])
3305         return YES;
3306     
3307     if (m_object->isWebArea() && [attributeName isEqualToString:NSAccessibilityCaretBrowsingEnabledAttribute])
3308         return YES;
3309     
3310     return NO;
3311 }
3312
3313 // accessibilityShouldUseUniqueId is an AppKit method we override so that
3314 // objects will be given a unique ID, and therefore allow AppKit to know when they
3315 // become obsolete (e.g. when the user navigates to a new web page, making this one
3316 // unrendered but not deallocated because it is in the back/forward cache).
3317 // It is important to call NSAccessibilityUnregisterUniqueIdForUIElement in the
3318 // appropriate place (e.g. dealloc) to remove these non-retained references from
3319 // AppKit's id mapping tables. We do this in detach by calling unregisterUniqueIdForUIElement.
3320 //
3321 // Registering an object is also required for observing notifications. Only registered objects can be observed.
3322 - (BOOL)accessibilityIsIgnored
3323 {
3324     if (![self updateObjectBackingStore])
3325         return YES;
3326     
3327     if (m_object->isAttachment())
3328         return [[self attachmentView] accessibilityIsIgnored];
3329     return m_object->accessibilityIsIgnored();
3330 }
3331
3332 - (NSArray* )accessibilityParameterizedAttributeNames
3333 {
3334     if (![self updateObjectBackingStore])
3335         return nil;
3336     
3337     if (m_object->isAttachment())
3338         return nil;
3339     
3340     static NSArray* paramAttrs = nil;
3341     static NSArray* textParamAttrs = nil;
3342     static NSArray* tableParamAttrs = nil;
3343     static NSArray* webAreaParamAttrs = nil;
3344     if (paramAttrs == nil) {
3345         paramAttrs = [[NSArray alloc] initWithObjects:
3346                       @"AXUIElementForTextMarker",
3347                       @"AXTextMarkerRangeForUIElement",
3348                       @"AXLineForTextMarker",
3349                       @"AXTextMarkerRangeForLine",
3350                       @"AXStringForTextMarkerRange",
3351                       @"AXTextMarkerForPosition",
3352                       @"AXBoundsForTextMarkerRange",
3353                       @"AXAttributedStringForTextMarkerRange",
3354                       @"AXTextMarkerRangeForUnorderedTextMarkers",
3355                       @"AXNextTextMarkerForTextMarker",
3356                       @"AXPreviousTextMarkerForTextMarker",
3357                       @"AXLeftWordTextMarkerRangeForTextMarker",
3358                       @"AXRightWordTextMarkerRangeForTextMarker",
3359                       @"AXLeftLineTextMarkerRangeForTextMarker",
3360                       @"AXRightLineTextMarkerRangeForTextMarker",
3361                       @"AXSentenceTextMarkerRangeForTextMarker",
3362                       @"AXParagraphTextMarkerRangeForTextMarker",
3363                       @"AXNextWordEndTextMarkerForTextMarker",
3364                       @"AXPreviousWordStartTextMarkerForTextMarker",
3365                       @"AXNextLineEndTextMarkerForTextMarker",
3366                       @"AXPreviousLineStartTextMarkerForTextMarker",
3367                       @"AXNextSentenceEndTextMarkerForTextMarker",
3368                       @"AXPreviousSentenceStartTextMarkerForTextMarker",
3369                       @"AXNextParagraphEndTextMarkerForTextMarker",
3370                       @"AXPreviousParagraphStartTextMarkerForTextMarker",
3371                       @"AXStyleTextMarkerRangeForTextMarker",
3372                       @"AXLengthForTextMarkerRange",
3373                       NSAccessibilityBoundsForRangeParameterizedAttribute,
3374                       NSAccessibilityStringForRangeParameterizedAttribute,
3375                       NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute,
3376                       NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute,
3377                       NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute,
3378                       NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute,
3379                       NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute,
3380                       NSAccessibilitySelectTextWithCriteriaParameterizedAttribute,
3381                       nil];
3382     }
3383     
3384     if (textParamAttrs == nil) {
3385         NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
3386         [tempArray addObject:(NSString*)kAXLineForIndexParameterizedAttribute];
3387         [tempArray addObject:(NSString*)kAXRangeForLineParameterizedAttribute];
3388         [tempArray addObject:(NSString*)kAXStringForRangeParameterizedAttribute];
3389         [tempArray addObject:(NSString*)kAXRangeForPositionParameterizedAttribute];
3390         [tempArray addObject:(NSString*)kAXRangeForIndexParameterizedAttribute];
3391         [tempArray addObject:(NSString*)kAXBoundsForRangeParameterizedAttribute];
3392         [tempArray addObject:(NSString*)kAXRTFForRangeParameterizedAttribute];
3393         [tempArray addObject:(NSString*)kAXAttributedStringForRangeParameterizedAttribute];
3394         [tempArray addObject:(NSString*)kAXStyleRangeForIndexParameterizedAttribute];
3395         textParamAttrs = [[NSArray alloc] initWithArray:tempArray];
3396         [tempArray release];
3397     }
3398     if (tableParamAttrs == nil) {
3399         NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
3400         [tempArray addObject:NSAccessibilityCellForColumnAndRowParameterizedAttribute];
3401         tableParamAttrs = [[NSArray alloc] initWithArray:tempArray];
3402         [tempArray release];
3403     }
3404     if (!webAreaParamAttrs) {
3405         NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
3406         [tempArray addObject:NSAccessibilityTextMarkerForIndexParameterizedAttribute];
3407         [tempArray addObject:NSAccessibilityTextMarkerIsValidParameterizedAttribute];
3408         [tempArray addObject:NSAccessibilityIndexForTextMarkerParameterizedAttribute];
3409         webAreaParamAttrs = [[NSArray alloc] initWithArray:tempArray];
3410         [tempArray release];
3411     }
3412     
3413     if (m_object->isPasswordField())
3414         return @[ NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute ];
3415     
3416     if (!m_object->isAccessibilityRenderObject())
3417         return paramAttrs;
3418     
3419     if (m_object->isTextControl())
3420         return textParamAttrs;
3421     
3422     if (is<AccessibilityTable>(*m_object) && downcast<AccessibilityTable>(*m_object).isExposableThroughAccessibility())
3423         return tableParamAttrs;
3424     
3425     if (m_object->isMenuRelated())
3426         return nil;
3427     
3428     if (m_object->isWebArea())
3429         return webAreaParamAttrs;
3430     
3431     return paramAttrs;
3432 }
3433
3434 #pragma clang diagnostic push
3435 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
3436
3437 - (void)accessibilityPerformPressAction
3438 {
3439     // In case anything we do by performing the press action causes an alert or other modal
3440     // behaviors, we need to return now, so that VoiceOver doesn't hang indefinitely.
3441     dispatch_async(dispatch_get_main_queue(), ^ {
3442         [self _accessibilityPerformPressAction];
3443     });
3444 }
3445
3446 - (void)_accessibilityPerformPressAction
3447 {
3448     if (![self updateObjectBackingStore])
3449         return;
3450     
3451     if (m_object->isAttachment())
3452         [[self attachmentView] accessibilityPerformAction:NSAccessibilityPressAction];
3453     else
3454         m_object->press();
3455 }
3456
3457 - (void)accessibilityPerformIncrementAction
3458 {
3459     if (![self updateObjectBackingStore])
3460         return;
3461     
3462     if (m_object->isAttachment())
3463         [[self attachmentView] accessibilityPerformAction:NSAccessibilityIncrementAction];
3464     else
3465         m_object->increment();
3466 }
3467
3468 - (void)accessibilityPerformDecrementAction
3469 {
3470     if (![self updateObjectBackingStore])
3471         return;
3472     
3473     if (m_object->isAttachment())
3474         [[self attachmentView] accessibilityPerformAction:NSAccessibilityDecrementAction];
3475     else
3476         m_object->decrement();
3477 }
3478
3479 #pragma clang diagnostic pop
3480
3481 - (void)accessibilityPerformShowMenuAction
3482 {
3483     if (m_object->roleValue() == ComboBoxRole)
3484         m_object->setIsExpanded(true);
3485     else {
3486         // This needs to be performed in an iteration of the run loop that did not start from an AX call.
3487         // If it's the same run loop iteration, the menu open notification won't be sent
3488         [self performSelector:@selector(accessibilityShowContextMenu) withObject:nil afterDelay:0.0];
3489     }
3490 }
3491
3492 - (void)accessibilityShowContextMenu
3493 {
3494     if (!m_object)
3495         return;
3496     
3497     Page* page = m_object->page();
3498     if (!page)
3499         return;
3500     
3501     IntRect rect = snappedIntRect(m_object->elementRect());
3502     FrameView* frameView = m_object->documentFrameView();
3503     
3504     // On WK2, we need to account for the scroll position.
3505     // On WK1, this isn't necessary, it's taken care of by the attachment views.
3506     if (frameView && !frameView->platformWidget()) {
3507         // Find the appropriate scroll view to use to convert the contents to the window.
3508         for (AccessibilityObject* parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
3509             if (is<AccessibilityScrollView>(*parent)) {
3510                 ScrollView* scrollView = downcast<AccessibilityScrollView>(*parent).scrollView();
3511                 rect = scrollView->contentsToRootView(rect);
3512                 break;
3513             }
3514         }
3515     }
3516     
3517     page->contextMenuController().showContextMenuAt(page->mainFrame(), rect.center());
3518 }
3519
3520