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