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