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