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