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