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