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