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