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