filterRegion and outsets of referenced SVG filter are calculated incorrectly
[WebKit-https.git] / Tools / WebKitTestRunner / InjectedBundle / mac / AccessibilityUIElementMac.mm
1 /*
2  * Copyright (C) 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #import "config.h"
27 #import "AccessibilityCommonMac.h"
28
29 #if HAVE(ACCESSIBILITY)
30
31 #import "AccessibilityNotificationHandler.h"
32 #import "AccessibilityUIElement.h"
33 #import "InjectedBundle.h"
34 #import "InjectedBundlePage.h"
35 #import "JSBasics.h"
36 #import <AppKit/NSAccessibility.h>
37 #import <Foundation/Foundation.h>
38 #import <JavaScriptCore/JSStringRefCF.h>
39 #import <JavaScriptCore/JSObjectRef.h>
40 #import <WebKit/WKBundleFrame.h>
41 #import <wtf/RetainPtr.h>
42 #import <wtf/Vector.h>
43 #import <wtf/cocoa/VectorCocoa.h>
44
45 #define NSAccessibilityDOMIdentifierAttribute @"AXDOMIdentifier"
46
47 #ifndef NSAccessibilityOwnsAttribute
48 #define NSAccessibilityOwnsAttribute @"AXOwns"
49 #endif
50
51 #ifndef NSAccessibilityGrabbedAttribute
52 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
53 #endif
54
55 #ifndef NSAccessibilityDropEffectsAttribute
56 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
57 #endif
58
59 #ifndef NSAccessibilityPathAttribute
60 #define NSAccessibilityPathAttribute @"AXPath"
61 #endif
62
63 #ifndef NSAccessibilityARIACurrentAttribute
64 #define NSAccessibilityARIACurrentAttribute @"AXARIACurrent"
65 #endif
66
67 // Text
68 #ifndef NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute
69 #define NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute @"AXEndTextMarkerForBounds"
70 #endif
71
72 #ifndef NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute
73 #define NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute @"AXStartTextMarkerForBounds"
74 #endif
75
76 #ifndef NSAccessibilitySelectedTextMarkerRangeAttribute
77 #define NSAccessibilitySelectedTextMarkerRangeAttribute @"AXSelectedTextMarkerRange"
78 #endif
79
80 typedef void (*AXPostedNotificationCallback)(id element, NSString* notification, void* context);
81
82 @interface NSObject (WebKitAccessibilityAdditions)
83 - (BOOL)isIsolatedObject;
84 - (BOOL)accessibilityReplaceRange:(NSRange)range withText:(NSString *)string;
85 - (BOOL)accessibilityInsertText:(NSString *)text;
86 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
87 - (NSUInteger)accessibilityIndexOfChild:(id)child;
88 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute;
89 - (void)_accessibilityScrollToMakeVisibleWithSubFocus:(NSRect)rect;
90 - (void)_accessibilityScrollToGlobalPoint:(NSPoint)point;
91 - (void)_accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName;
92 @end
93
94 namespace WTR {
95
96 RefPtr<AccessibilityController> AccessibilityUIElement::s_controller;
97
98 AccessibilityUIElement::AccessibilityUIElement(id element)
99     : m_element(element)
100 {
101     if (!s_controller)
102         s_controller = InjectedBundle::singleton().accessibilityController();
103 }
104
105 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
106     : JSWrappable()
107     , m_element(other.m_element)
108 {
109 }
110
111 AccessibilityUIElement::~AccessibilityUIElement()
112 {
113 }
114
115 bool AccessibilityUIElement::isEqual(AccessibilityUIElement* otherElement)
116 {
117     if (!otherElement)
118         return false;
119     return platformUIElement() == otherElement->platformUIElement();
120 }
121
122 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
123 bool AccessibilityUIElement::isIsolatedObject() const
124 {
125     return [m_element isIsolatedObject];
126 }
127 #endif
128
129 RetainPtr<NSArray> supportedAttributes(id element)
130 {
131     RetainPtr<NSArray> attributes;
132
133     BEGIN_AX_OBJC_EXCEPTIONS
134     AccessibilityUIElement::s_controller->executeOnAXThreadAndWait([&attributes, &element] {
135         attributes = [element accessibilityAttributeNames];
136     });
137     END_AX_OBJC_EXCEPTIONS
138
139     return attributes;
140 }
141
142 static id attributeValue(id element, NSString *attribute)
143 {
144     // The given `element` may not respond to `accessibilityAttributeValue`, so first check to see if it responds to the attribute-specific selector.
145     if ([attribute isEqual:NSAccessibilityChildrenAttribute] && [element respondsToSelector:@selector(accessibilityChildren)])
146         return [element accessibilityChildren];
147     if ([attribute isEqual:NSAccessibilityDescriptionAttribute] && [element respondsToSelector:@selector(accessibilityLabel)])
148         return [element accessibilityLabel];
149     if ([attribute isEqual:NSAccessibilityParentAttribute] && [element respondsToSelector:@selector(accessibilityParent)])
150         return [element accessibilityParent];
151     if ([attribute isEqual:NSAccessibilityRoleAttribute] && [element respondsToSelector:@selector(accessibilityRole)])
152         return [element accessibilityRole];
153     if ([attribute isEqual:NSAccessibilityValueAttribute] && [element respondsToSelector:@selector(accessibilityValue)])
154         return [element accessibilityValue];
155     if ([attribute isEqual:NSAccessibilityFocusedUIElementAttribute] && [element respondsToSelector:@selector(accessibilityFocusedUIElement)])
156         return [element accessibilityFocusedUIElement];
157
158     return [element accessibilityAttributeValue:attribute];
159 }
160
161 void setAttributeValue(id element, NSString* attribute, id value, bool synchronous = false)
162 {
163     BEGIN_AX_OBJC_EXCEPTIONS
164     AccessibilityUIElement::s_controller->executeOnAXThreadAndWait([&element, &attribute, &value, &synchronous] {
165         // FIXME: should always be asynchronous, fix tests.
166         synchronous ? [element _accessibilitySetValue:value forAttribute:attribute] :
167             [element accessibilitySetValue:value forAttribute:attribute];
168     });
169     END_AX_OBJC_EXCEPTIONS
170 }
171
172 NSString *AccessibilityUIElement::descriptionOfValue(id valueObject) const
173 {
174     if (!valueObject)
175         return nil;
176
177     if ([valueObject isKindOfClass:[NSArray class]])
178         return [NSString stringWithFormat:@"<array of size %lu>", static_cast<unsigned long>([(NSArray*)valueObject count])];
179
180     if ([valueObject isKindOfClass:[NSNumber class]])
181         return [(NSNumber*)valueObject stringValue];
182
183     if ([valueObject isKindOfClass:[NSValue class]]) {
184         NSString *type = [NSString stringWithCString:[valueObject objCType] encoding:NSASCIIStringEncoding];
185         NSValue *value = (NSValue *)valueObject;
186         if ([type rangeOfString:@"NSRect"].length > 0)
187             return [NSString stringWithFormat:@"NSRect: %@", NSStringFromRect([value rectValue])];
188         if ([type rangeOfString:@"NSPoint"].length > 0)
189             return [NSString stringWithFormat:@"NSPoint: %@", NSStringFromPoint([value pointValue])];
190         if ([type rangeOfString:@"NSSize"].length > 0)
191             return [NSString stringWithFormat:@"NSSize: %@", NSStringFromSize([value sizeValue])];
192         if ([type rangeOfString:@"NSRange"].length > 0)
193             return [NSString stringWithFormat:@"NSRange: %@", NSStringFromRange([value rangeValue])];
194     }
195
196     // Strip absolute URL paths
197     NSString *description = [valueObject description];
198     NSRange range = [description rangeOfString:@"LayoutTests"];
199     if (range.length)
200         return [description substringFromIndex:range.location];
201
202     // Strip pointer locations
203     if ([description rangeOfString:@"0x"].length) {
204         auto role = attributeValue(NSAccessibilityRoleAttribute);
205         auto title = attributeValue(NSAccessibilityTitleAttribute);
206         if ([title length])
207             return [NSString stringWithFormat:@"<%@: '%@'>", role.get(), title.get()];
208         return [NSString stringWithFormat:@"<%@>", role.get()];
209     }
210
211     return [valueObject description];
212 }
213
214 static JSRetainPtr<JSStringRef> concatenateAttributeAndValue(NSString* attribute, NSString* value)
215 {
216     Vector<UniChar> buffer([attribute length]);
217     [attribute getCharacters:buffer.data()];
218     buffer.append(':');
219     buffer.append(' ');
220
221     Vector<UniChar> valueBuffer([value length]);
222     [value getCharacters:valueBuffer.data()];
223     buffer.appendVector(valueBuffer);
224
225     return adopt(JSStringCreateWithCharacters(buffer.data(), buffer.size()));
226 }
227
228 static JSRetainPtr<JSStringRef> descriptionOfElements(const Vector<RefPtr<AccessibilityUIElement>>& elements)
229 {
230     NSMutableString *allElementString = [NSMutableString string];
231     for (auto element : elements) {
232         NSString *attributes = [NSString stringWithJSStringRef:element->allAttributes().get()];
233         [allElementString appendFormat:@"%@\n------------\n", attributes];
234     }
235
236     return [allElementString createJSStringRef];
237 }
238
239 static NSDictionary *selectTextParameterizedAttributeForCriteria(JSContextRef context, JSStringRef ambiguityResolution, JSValueRef searchStrings, JSStringRef replacementString, JSStringRef activity)
240 {
241     NSMutableDictionary *parameterizedAttribute = [NSMutableDictionary dictionary];
242     
243     if (ambiguityResolution)
244         [parameterizedAttribute setObject:[NSString stringWithJSStringRef:ambiguityResolution] forKey:@"AXSelectTextAmbiguityResolution"];
245     
246     if (searchStrings) {
247         NSMutableArray *searchStringsParameter = [NSMutableArray array];
248         if (JSValueIsString(context, searchStrings))
249             [searchStringsParameter addObject:toWTFString(context, searchStrings)];
250         else {
251             JSObjectRef searchStringsArray = JSValueToObject(context, searchStrings, nullptr);
252             unsigned searchStringsArrayLength = arrayLength(context, searchStringsArray);
253             for (unsigned i = 0; i < searchStringsArrayLength; ++i)
254                 [searchStringsParameter addObject:toWTFString(context, JSObjectGetPropertyAtIndex(context, searchStringsArray, i, nullptr))];
255         }
256         [parameterizedAttribute setObject:searchStringsParameter forKey:@"AXSelectTextSearchStrings"];
257     }
258     
259     if (replacementString) {
260         [parameterizedAttribute setObject:@"AXSelectTextActivityFindAndReplace" forKey:@"AXSelectTextActivity"];
261         [parameterizedAttribute setObject:[NSString stringWithJSStringRef:replacementString] forKey:@"AXSelectTextReplacementString"];
262     } else
263         [parameterizedAttribute setObject:@"AXSelectTextActivityFindAndSelect" forKey:@"AXSelectTextActivity"];
264     
265     if (activity)
266         [parameterizedAttribute setObject:[NSString stringWithJSStringRef:activity] forKey:@"AXSelectTextActivity"];
267     
268     return parameterizedAttribute;
269 }
270
271 static NSDictionary *searchTextParameterizedAttributeForCriteria(JSContextRef context, JSValueRef searchStrings, JSStringRef startFrom, JSStringRef direction)
272 {
273     NSMutableDictionary *parameterizedAttribute = [NSMutableDictionary dictionary];
274
275     if (searchStrings) {
276         NSMutableArray *searchStringsParameter = [NSMutableArray array];
277         if (JSValueIsString(context, searchStrings))
278             [searchStringsParameter addObject:toWTFString(context, searchStrings)];
279         else {
280             JSObjectRef searchStringsArray = JSValueToObject(context, searchStrings, nullptr);
281             unsigned searchStringsArrayLength = arrayLength(context, searchStringsArray);
282             for (unsigned i = 0; i < searchStringsArrayLength; ++i)
283                 [searchStringsParameter addObject:toWTFString(context, JSObjectGetPropertyAtIndex(context, searchStringsArray, i, nullptr))];
284         }
285         [parameterizedAttribute setObject:searchStringsParameter forKey:@"AXSearchTextSearchStrings"];
286     }
287
288     if (startFrom)
289         [parameterizedAttribute setObject:[NSString stringWithJSStringRef:startFrom] forKey:@"AXSearchTextStartFrom"];
290
291     if (direction)
292         [parameterizedAttribute setObject:[NSString stringWithJSStringRef:direction] forKey:@"AXSearchTextDirection"];
293
294     return parameterizedAttribute;
295 }
296
297 static NSDictionary *misspellingSearchParameterizedAttributeForCriteria(AccessibilityTextMarkerRange* start, bool forward)
298 {
299     if (!start || !start->platformTextMarkerRange())
300         return nil;
301
302     NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
303
304     [parameters setObject:start->platformTextMarkerRange() forKey:@"AXStartTextMarkerRange"];
305     [parameters setObject:[NSNumber numberWithBool:forward] forKey:@"AXSearchTextDirection"];
306
307     return parameters;
308 }
309
310 RetainPtr<id> AccessibilityUIElement::attributeValue(NSString *attributeName) const
311 {
312     RetainPtr<id> value;
313
314     BEGIN_AX_OBJC_EXCEPTIONS
315     s_controller->executeOnAXThreadAndWait([this, &attributeName, &value] {
316         value = WTR::attributeValue(m_element.get(), attributeName);
317     });
318     END_AX_OBJC_EXCEPTIONS
319
320     return value;
321 }
322
323 RetainPtr<id> AccessibilityUIElement::attributeValueForParameter(NSString *attributeName, id parameter) const
324 {
325     RetainPtr<id> value;
326
327     BEGIN_AX_OBJC_EXCEPTIONS
328     s_controller->executeOnAXThreadAndWait([this, &attributeName, &parameter, &value] {
329         value = [m_element accessibilityAttributeValue:attributeName forParameter:parameter];
330     });
331     END_AX_OBJC_EXCEPTIONS
332
333     return value;
334 }
335
336 JSRetainPtr<JSStringRef> AccessibilityUIElement::domIdentifier() const
337 {
338     return stringAttributeValue(NSAccessibilityDOMIdentifierAttribute);
339 }
340
341 void AccessibilityUIElement::getLinkedUIElements(Vector<RefPtr<AccessibilityUIElement>>& elementVector)
342 {
343     elementVector = makeVector<RefPtr<AccessibilityUIElement>>(attributeValue(NSAccessibilityLinkedUIElementsAttribute).get());
344 }
345
346 void AccessibilityUIElement::getDocumentLinks(Vector<RefPtr<AccessibilityUIElement>>& elementVector)
347 {
348     elementVector = makeVector<RefPtr<AccessibilityUIElement>>(attributeValue(@"AXLinkUIElements").get());
349 }
350
351 void AccessibilityUIElement::getUIElementsWithAttribute(JSStringRef attribute, Vector<RefPtr<AccessibilityUIElement>>& elements) const
352 {
353     auto value = attributeValue([NSString stringWithJSStringRef:attribute]);
354     if ([value isKindOfClass:[NSArray class]])
355         elements = makeVector<RefPtr<AccessibilityUIElement>>(value.get());
356 }
357
358 JSValueRef AccessibilityUIElement::children() const
359 {
360     BEGIN_AX_OBJC_EXCEPTIONS
361     return makeJSArray(makeVector<RefPtr<AccessibilityUIElement>>(attributeValue(NSAccessibilityChildrenAttribute).get()));
362     END_AX_OBJC_EXCEPTIONS
363
364     return nullptr;
365 }
366
367 void AccessibilityUIElement::getChildren(Vector<RefPtr<AccessibilityUIElement> >& elementVector)
368 {
369     elementVector = makeVector<RefPtr<AccessibilityUIElement>>(attributeValue(NSAccessibilityChildrenAttribute).get());
370 }
371
372 void AccessibilityUIElement::getChildrenWithRange(Vector<RefPtr<AccessibilityUIElement> >& elementVector, unsigned location, unsigned length)
373 {
374     BEGIN_AX_OBJC_EXCEPTIONS
375     RetainPtr<NSArray> children;
376     s_controller->executeOnAXThreadAndWait([&children, location, length, this] {
377         children = [m_element accessibilityArrayAttributeValues:NSAccessibilityChildrenAttribute index:location maxCount:length];
378     });
379     elementVector = makeVector<RefPtr<AccessibilityUIElement>>(children.get());
380     END_AX_OBJC_EXCEPTIONS
381 }
382
383 JSValueRef AccessibilityUIElement::rowHeaders() const
384 {
385     BEGIN_AX_OBJC_EXCEPTIONS
386     Vector<RefPtr<AccessibilityUIElement>> elements;
387     auto value = attributeValue(NSAccessibilityRowHeaderUIElementsAttribute);
388     if ([value isKindOfClass:[NSArray class]])
389         elements = makeVector<RefPtr<AccessibilityUIElement>>(value.get());
390     return makeJSArray(elements);
391     END_AX_OBJC_EXCEPTIONS
392 }
393
394 JSValueRef AccessibilityUIElement::columnHeaders() const
395 {
396     BEGIN_AX_OBJC_EXCEPTIONS
397     Vector<RefPtr<AccessibilityUIElement>> elements;
398     auto value = attributeValue(NSAccessibilityColumnHeaderUIElementsAttribute);
399     if ([value isKindOfClass:[NSArray class]])
400         elements = makeVector<RefPtr<AccessibilityUIElement>>(value.get());
401     return makeJSArray(elements);
402     END_AX_OBJC_EXCEPTIONS
403 }
404
405 int AccessibilityUIElement::childrenCount()
406 {
407     Vector<RefPtr<AccessibilityUIElement> > children;
408     getChildren(children);
409     
410     return children.size();
411 }
412
413 RefPtr<AccessibilityUIElement> AccessibilityUIElement::elementAtPoint(int x, int y)
414 {
415     RetainPtr<id> element;
416     s_controller->executeOnAXThreadAndWait([&x, &y, &element, this] {
417         element = [m_element accessibilityHitTest:NSMakePoint(x, y)];
418     });
419
420     if (!element)
421         return nullptr;
422
423     return AccessibilityUIElement::create(element.get());
424 }
425
426 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
427 {
428     unsigned index;
429     id platformElement = element->platformUIElement();
430     s_controller->executeOnAXThreadAndWait([&platformElement, &index, this] {
431         index = [m_element accessibilityIndexOfChild:platformElement];
432     });
433     return index;
434 }
435
436 RefPtr<AccessibilityUIElement> AccessibilityUIElement::childAtIndex(unsigned index)
437 {
438     Vector<RefPtr<AccessibilityUIElement>> children;
439     getChildrenWithRange(children, index, 1);
440
441     if (children.size() == 1)
442         return children[0];
443     return nullptr;
444 }
445
446 RefPtr<AccessibilityUIElement> AccessibilityUIElement::elementForAttribute(NSString* attribute) const
447 {
448     auto element = attributeValue(attribute);
449     return element ? AccessibilityUIElement::create(element.get()) : RefPtr<AccessibilityUIElement>();
450 }
451
452 RefPtr<AccessibilityUIElement> AccessibilityUIElement::elementForAttributeAtIndex(NSString* attribute, unsigned index) const
453 {
454     auto elements = attributeValue(attribute);
455     return index < [elements count] ? AccessibilityUIElement::create([elements objectAtIndex:index]) : RefPtr<AccessibilityUIElement>();
456 }
457
458 RefPtr<AccessibilityUIElement> AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
459 {
460     return elementForAttributeAtIndex(NSAccessibilityLinkedUIElementsAttribute, index);
461 }
462
463 JSValueRef AccessibilityUIElement::detailsElements() const
464 {
465     BEGIN_AX_OBJC_EXCEPTIONS
466     auto elements = attributeValue(@"AXDetailsElements");
467     if ([elements isKindOfClass:NSArray.class])
468         return makeJSArray(makeVector<RefPtr<AccessibilityUIElement>>(elements.get()));
469     END_AX_OBJC_EXCEPTIONS
470
471     return { };
472 }
473
474 JSValueRef AccessibilityUIElement::errorMessageElements() const
475 {
476     BEGIN_AX_OBJC_EXCEPTIONS
477     auto elements = attributeValue(@"AXErrorMessageElements");
478     if ([elements isKindOfClass:NSArray.class])
479         return makeJSArray(makeVector<RefPtr<AccessibilityUIElement>>(elements.get()));
480     END_AX_OBJC_EXCEPTIONS
481
482     return { };
483 }
484
485 RefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
486 {
487     return elementForAttributeAtIndex(NSAccessibilityOwnsAttribute, index);
488 }
489
490 RefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
491 {
492     return elementForAttributeAtIndex(NSAccessibilityLinkedUIElementsAttribute, index);
493 }
494
495 RefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaControlsElementAtIndex(unsigned index)
496 {
497     return elementForAttributeAtIndex(@"AXARIAControls", index);
498 }
499
500 RefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaDetailsElementAtIndex(unsigned index)
501 {
502     return elementForAttributeAtIndex(@"AXDetailsElements", index);
503 }
504
505 RefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaErrorMessageElementAtIndex(unsigned index)
506 {
507     return elementForAttributeAtIndex(@"AXErrorMessageElements", index);
508 }
509
510 RefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
511 {
512     return elementForAttributeAtIndex(NSAccessibilityDisclosedRowsAttribute, index);
513 }
514
515 RefPtr<AccessibilityUIElement> AccessibilityUIElement::rowAtIndex(unsigned index)
516 {
517     return elementForAttributeAtIndex(NSAccessibilityRowsAttribute, index);
518 }
519
520 RefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedChildAtIndex(unsigned index) const
521 {
522     return elementForAttributeAtIndex(NSAccessibilitySelectedChildrenAttribute, index);
523 }
524
525 unsigned AccessibilityUIElement::selectedChildrenCount() const
526 {
527     unsigned count = 0;
528
529     BEGIN_AX_OBJC_EXCEPTIONS
530     s_controller->executeOnAXThreadAndWait([&count, this] {
531         count = [m_element accessibilityArrayAttributeCount:NSAccessibilitySelectedChildrenAttribute];
532     });
533     END_AX_OBJC_EXCEPTIONS
534
535     return count;
536 }
537
538 RefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedRowAtIndex(unsigned index)
539 {
540     return elementForAttributeAtIndex(NSAccessibilitySelectedRowsAttribute, index);
541 }
542
543 RefPtr<AccessibilityUIElement> AccessibilityUIElement::titleUIElement()
544 {
545     return elementForAttribute(NSAccessibilityTitleUIElementAttribute);
546 }
547
548 RefPtr<AccessibilityUIElement> AccessibilityUIElement::parentElement()
549 {
550     return elementForAttribute(NSAccessibilityParentAttribute);
551 }
552
553 RefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedByRow()
554 {
555     return elementForAttribute(NSAccessibilityDisclosedByRowAttribute);
556 }
557
558 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfLinkedUIElements()
559 {
560     Vector<RefPtr<AccessibilityUIElement> > linkedElements;
561     getLinkedUIElements(linkedElements);
562     return descriptionOfElements(linkedElements);
563 }
564
565 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfDocumentLinks()
566 {
567     Vector<RefPtr<AccessibilityUIElement> > linkElements;
568     getDocumentLinks(linkElements);
569     return descriptionOfElements(linkElements);
570 }
571
572 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfChildren()
573 {
574     Vector<RefPtr<AccessibilityUIElement> > children;
575     getChildren(children);
576     return descriptionOfElements(children);
577 }
578
579 JSRetainPtr<JSStringRef> AccessibilityUIElement::allAttributes()
580 {
581     auto attributes = supportedAttributes(m_element.get());
582
583     NSMutableString *values = [NSMutableString string];
584     for (NSString *attribute in attributes.get()) {
585         // Exclude screen-specific values, since they can change depending on the system.
586         if ([attribute isEqualToString:@"AXPosition"]
587             || [attribute isEqualToString:@"_AXPrimaryScreenHeight"]
588             || [attribute isEqualToString:@"AXRelativeFrame"])
589             continue;
590
591         RetainPtr<NSString> value = descriptionOfValue(attributeValue(attribute).get());
592         [values appendFormat:@"%@: %@\n", attribute, value.get()];
593     }
594
595     return [values createJSStringRef];
596 }
597
598 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringDescriptionOfAttributeValue(JSStringRef attribute)
599 {
600     auto value = attributeValue([NSString stringWithJSStringRef:attribute]);
601     NSString *valueDescription = descriptionOfValue(value.get());
602     return [valueDescription createJSStringRef];
603 }
604
605 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
606 {
607     return stringAttributeValue([NSString stringWithJSStringRef:attribute]);
608 }
609
610 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringAttributeValue(NSString *attribute) const
611 {
612     BEGIN_AX_OBJC_EXCEPTIONS
613     auto value = attributeValue(attribute);
614     if ([value isKindOfClass:[NSString class]])
615         return [value createJSStringRef];
616     END_AX_OBJC_EXCEPTIONS
617
618     return nullptr;
619 }
620
621 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
622 {
623     return numberAttributeValue([NSString stringWithJSStringRef:attribute]);
624 }
625
626 double AccessibilityUIElement::numberAttributeValue(NSString *attribute) const
627 {
628     BEGIN_AX_OBJC_EXCEPTIONS
629     auto value = attributeValue(attribute);
630     if ([value isKindOfClass:[NSNumber class]])
631         return [value doubleValue];
632     END_AX_OBJC_EXCEPTIONS
633
634     return 0;
635 }
636
637 JSValueRef AccessibilityUIElement::uiElementArrayAttributeValue(JSStringRef attribute) const
638 {
639     Vector<RefPtr<AccessibilityUIElement>> elements;
640     getUIElementsWithAttribute(attribute, elements);
641     return makeJSArray(elements);
642 }
643
644 RefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementAttributeValue(JSStringRef attribute) const
645 {
646     if (auto value = attributeValue([NSString stringWithJSStringRef:attribute]))
647         return AccessibilityUIElement::create(value.get());
648     return nullptr;
649 }
650
651 bool AccessibilityUIElement::boolAttributeValue(NSString *attribute) const
652 {
653     BEGIN_AX_OBJC_EXCEPTIONS
654     auto value = attributeValue(attribute);
655     if ([value isKindOfClass:[NSNumber class]])
656         return [value boolValue];
657     END_AX_OBJC_EXCEPTIONS
658
659     return false;
660 }
661
662 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
663 {
664     return boolAttributeValue([NSString stringWithJSStringRef:attribute]);
665 }
666
667 void AccessibilityUIElement::attributeValueAsync(JSStringRef attribute, JSValueRef callback)
668 {
669     if (!attribute || !callback)
670         return;
671
672     BEGIN_AX_OBJC_EXCEPTIONS
673     s_controller->executeOnAXThread([attribute = retainPtr([NSString stringWithJSStringRef:attribute]), callback = WTFMove(callback), this] () mutable {
674         id value = [m_element accessibilityAttributeValue:attribute.get()];
675         if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]])
676             value = [value description];
677         
678         s_controller->executeOnMainThread([value = retainPtr(value), callback = WTFMove(callback)] () {
679             auto mainFrame = WKBundlePageGetMainFrame(InjectedBundle::singleton().page()->page());
680             auto context = WKBundleFrameGetJavaScriptContext(mainFrame);
681
682             JSValueRef arguments[1];
683             arguments[0] = makeValueRefForValue(context, value.get());
684             JSObjectCallAsFunction(context, const_cast<JSObjectRef>(callback), 0, 1, arguments, 0);
685         });
686     });
687     END_AX_OBJC_EXCEPTIONS
688 }
689
690 void AccessibilityUIElement::setBoolAttributeValue(JSStringRef attribute, bool value)
691 {
692     setAttributeValue(m_element.get(), [NSString stringWithJSStringRef:attribute], @(value), true);
693 }
694
695 void AccessibilityUIElement::setValue(JSStringRef value)
696 {
697     setAttributeValue(m_element.get(), NSAccessibilityValueAttribute, [NSString stringWithJSStringRef:value]);
698 }
699
700 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
701 {
702     BEGIN_AX_OBJC_EXCEPTIONS
703     return [m_element accessibilityIsAttributeSettable:[NSString stringWithJSStringRef:attribute]];
704     END_AX_OBJC_EXCEPTIONS
705     
706     return false;
707 }
708
709 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
710 {
711     BEGIN_AX_OBJC_EXCEPTIONS
712     return [supportedAttributes(m_element.get()) containsObject:[NSString stringWithJSStringRef:attribute]];
713     END_AX_OBJC_EXCEPTIONS
714
715     return false;
716 }
717
718 JSRetainPtr<JSStringRef> AccessibilityUIElement::parameterizedAttributeNames()
719 {
720     NSArray* supportedParameterizedAttributes = [m_element accessibilityParameterizedAttributeNames];
721     
722     NSMutableString* attributesString = [NSMutableString string];
723     for (NSUInteger i = 0; i < [supportedParameterizedAttributes count]; ++i) {
724         [attributesString appendFormat:@"%@\n", [supportedParameterizedAttributes objectAtIndex:i]];
725     }
726     
727     return [attributesString createJSStringRef];
728 }
729
730 JSRetainPtr<JSStringRef> AccessibilityUIElement::role()
731 {
732     BEGIN_AX_OBJC_EXCEPTIONS
733     NSString *role = descriptionOfValue(attributeValue(NSAccessibilityRoleAttribute).get());
734     return concatenateAttributeAndValue(@"AXRole", role);
735     END_AX_OBJC_EXCEPTIONS
736
737     return nullptr;
738 }
739
740 JSRetainPtr<JSStringRef> AccessibilityUIElement::subrole()
741 {
742     BEGIN_AX_OBJC_EXCEPTIONS
743     NSString *subrole = descriptionOfValue(attributeValue(NSAccessibilitySubroleAttribute).get());
744     return concatenateAttributeAndValue(@"AXSubrole", subrole);
745     END_AX_OBJC_EXCEPTIONS
746
747     return nullptr;
748 }
749
750 JSRetainPtr<JSStringRef> AccessibilityUIElement::roleDescription()
751 {
752     BEGIN_AX_OBJC_EXCEPTIONS
753     NSString *role = descriptionOfValue(attributeValue(NSAccessibilityRoleDescriptionAttribute).get());
754     return concatenateAttributeAndValue(@"AXRoleDescription", role);
755     END_AX_OBJC_EXCEPTIONS
756
757     return nullptr;
758 }
759
760 JSRetainPtr<JSStringRef> AccessibilityUIElement::computedRoleString()
761 {
762     BEGIN_AX_OBJC_EXCEPTIONS
763     NSString *computedRoleString = descriptionOfValue(attributeValue(@"AXARIARole").get());
764     return [computedRoleString createJSStringRef];
765     END_AX_OBJC_EXCEPTIONS
766
767     return nullptr;
768 }
769
770 JSRetainPtr<JSStringRef> AccessibilityUIElement::title()
771 {
772     BEGIN_AX_OBJC_EXCEPTIONS
773     NSString *title = descriptionOfValue(attributeValue(NSAccessibilityTitleAttribute).get());
774     return concatenateAttributeAndValue(@"AXTitle", title);
775     END_AX_OBJC_EXCEPTIONS
776
777     return nullptr;
778 }
779
780 JSRetainPtr<JSStringRef> AccessibilityUIElement::description()
781 {
782     BEGIN_AX_OBJC_EXCEPTIONS
783     NSString *description = descriptionOfValue(attributeValue(NSAccessibilityDescriptionAttribute).get());
784     return concatenateAttributeAndValue(@"AXDescription", description);
785     END_AX_OBJC_EXCEPTIONS
786
787     return nullptr;
788 }
789
790 JSRetainPtr<JSStringRef> AccessibilityUIElement::orientation() const
791 {
792     BEGIN_AX_OBJC_EXCEPTIONS
793     NSString *description = descriptionOfValue(attributeValue(NSAccessibilityOrientationAttribute).get());
794     return concatenateAttributeAndValue(@"AXOrientation", description);    
795     END_AX_OBJC_EXCEPTIONS
796
797     return nullptr;
798 }
799
800 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringValue()
801 {
802     BEGIN_AX_OBJC_EXCEPTIONS
803     auto value = attributeValue(NSAccessibilityValueAttribute);
804     NSString *description = descriptionOfValue(value.get());
805     if (description)
806         return concatenateAttributeAndValue(@"AXValue", description);
807     END_AX_OBJC_EXCEPTIONS
808
809     return nullptr;
810 }
811
812 JSRetainPtr<JSStringRef> AccessibilityUIElement::language()
813 {
814     BEGIN_AX_OBJC_EXCEPTIONS
815     NSString *description = descriptionOfValue(attributeValue(@"AXLanguage").get());
816     return concatenateAttributeAndValue(@"AXLanguage", description);
817     END_AX_OBJC_EXCEPTIONS
818
819     return nullptr;
820 }
821
822 JSRetainPtr<JSStringRef> AccessibilityUIElement::helpText() const
823 {
824     BEGIN_AX_OBJC_EXCEPTIONS
825     NSString *description = descriptionOfValue(attributeValue(NSAccessibilityHelpAttribute).get());
826     return concatenateAttributeAndValue(@"AXHelp", description);
827     END_AX_OBJC_EXCEPTIONS
828     
829     return nullptr;
830 }
831
832 double AccessibilityUIElement::x()
833 {
834     BEGIN_AX_OBJC_EXCEPTIONS
835     auto positionValue = attributeValue(NSAccessibilityPositionAttribute);
836     return static_cast<double>([positionValue pointValue].x);    
837     END_AX_OBJC_EXCEPTIONS
838
839     return 0.0f;
840 }
841
842 double AccessibilityUIElement::y()
843 {
844     BEGIN_AX_OBJC_EXCEPTIONS
845     auto positionValue = attributeValue(NSAccessibilityPositionAttribute);
846     return static_cast<double>([positionValue pointValue].y);    
847     END_AX_OBJC_EXCEPTIONS
848
849     return 0.0f;
850 }
851
852 double AccessibilityUIElement::width()
853 {
854     BEGIN_AX_OBJC_EXCEPTIONS
855     auto sizeValue = attributeValue(NSAccessibilitySizeAttribute);
856     return static_cast<double>([sizeValue sizeValue].width);
857     END_AX_OBJC_EXCEPTIONS
858
859     return 0.0f;
860 }
861
862 double AccessibilityUIElement::height()
863 {
864     BEGIN_AX_OBJC_EXCEPTIONS
865     auto sizeValue = attributeValue(NSAccessibilitySizeAttribute);
866     return static_cast<double>([sizeValue sizeValue].height);
867     END_AX_OBJC_EXCEPTIONS
868
869     return 0.0f;
870 }
871
872 double AccessibilityUIElement::clickPointX()
873 {
874     BEGIN_AX_OBJC_EXCEPTIONS
875     auto positionValue = attributeValue(@"AXClickPoint");
876     return static_cast<double>([positionValue pointValue].x);        
877     END_AX_OBJC_EXCEPTIONS
878
879     return 0.0f;
880 }
881
882 double AccessibilityUIElement::clickPointY()
883 {
884     BEGIN_AX_OBJC_EXCEPTIONS
885     auto positionValue = attributeValue(@"AXClickPoint");
886     return static_cast<double>([positionValue pointValue].y);
887     END_AX_OBJC_EXCEPTIONS
888
889     return 0.0f;
890 }
891
892 JSRetainPtr<JSStringRef> AccessibilityUIElement::lineRectsAndText() const
893 {
894     BEGIN_AX_OBJC_EXCEPTIONS
895     auto lineRectsAndText = attributeValue(@"AXLineRectsAndText");
896     if (![lineRectsAndText isKindOfClass:NSArray.class])
897         return { };
898     return [[lineRectsAndText componentsJoinedByString:@"|"] createJSStringRef];
899     END_AX_OBJC_EXCEPTIONS
900
901     return { };
902 }
903
904 double AccessibilityUIElement::intValue() const
905 {
906     return numberAttributeValue(NSAccessibilityValueAttribute);
907 }
908
909 double AccessibilityUIElement::minValue()
910 {
911     return numberAttributeValue(NSAccessibilityMinValueAttribute);
912 }
913
914 double AccessibilityUIElement::maxValue()
915 {
916     return numberAttributeValue(NSAccessibilityMaxValueAttribute);
917 }
918
919 JSRetainPtr<JSStringRef> AccessibilityUIElement::valueDescription()
920 {
921     BEGIN_AX_OBJC_EXCEPTIONS
922     auto valueDescription = attributeValue(NSAccessibilityValueDescriptionAttribute);
923     if ([valueDescription isKindOfClass:[NSString class]])
924         return concatenateAttributeAndValue(@"AXValueDescription", valueDescription.get());
925     END_AX_OBJC_EXCEPTIONS
926
927     return nullptr;
928 }
929
930 int AccessibilityUIElement::insertionPointLineNumber()
931 {
932     BEGIN_AX_OBJC_EXCEPTIONS
933     auto value = attributeValue(NSAccessibilityInsertionPointLineNumberAttribute);
934     if ([value isKindOfClass:[NSNumber class]])
935         return [(NSNumber *)value intValue]; 
936     END_AX_OBJC_EXCEPTIONS
937
938     return -1;
939 }
940
941 bool AccessibilityUIElement::isPressActionSupported()
942 {
943     BEGIN_AX_OBJC_EXCEPTIONS
944     NSArray* actions = [m_element accessibilityActionNames];
945     return [actions containsObject:NSAccessibilityPressAction];
946     END_AX_OBJC_EXCEPTIONS
947     
948     return false;
949 }
950
951 bool AccessibilityUIElement::isIncrementActionSupported()
952 {
953     BEGIN_AX_OBJC_EXCEPTIONS
954     NSArray* actions = [m_element accessibilityActionNames];
955     return [actions containsObject:NSAccessibilityIncrementAction];
956     END_AX_OBJC_EXCEPTIONS
957     
958     return false;
959 }
960
961 bool AccessibilityUIElement::isDecrementActionSupported()
962 {
963     BEGIN_AX_OBJC_EXCEPTIONS
964     NSArray* actions = [m_element accessibilityActionNames];
965     return [actions containsObject:NSAccessibilityDecrementAction];
966     END_AX_OBJC_EXCEPTIONS
967     
968     return false;
969 }
970
971 bool AccessibilityUIElement::isEnabled()
972 {
973     return boolAttributeValue(NSAccessibilityEnabledAttribute);
974 }
975
976 bool AccessibilityUIElement::isRequired() const
977 {
978     return boolAttributeValue(@"AXRequired");
979 }
980
981 RefPtr<AccessibilityUIElement> AccessibilityUIElement::focusedElement() const
982 {
983     BEGIN_AX_OBJC_EXCEPTIONS
984     if (auto focus = attributeValue(NSAccessibilityFocusedUIElementAttribute))
985         return AccessibilityUIElement::create(focus.get());
986     END_AX_OBJC_EXCEPTIONS
987
988     return nullptr;
989 }
990
991 bool AccessibilityUIElement::isFocused() const
992 {
993     return boolAttributeValue(NSAccessibilityFocusedAttribute);
994 }
995
996 bool AccessibilityUIElement::isSelected() const
997 {
998     auto value = attributeValue(NSAccessibilitySelectedAttribute);
999     if ([value isKindOfClass:[NSNumber class]])
1000         return [value boolValue];
1001     return false;
1002 }
1003
1004 bool AccessibilityUIElement::isSelectedOptionActive() const
1005 {
1006     return false;
1007 }
1008
1009 bool AccessibilityUIElement::isIndeterminate() const
1010 {
1011     BEGIN_AX_OBJC_EXCEPTIONS
1012     auto value = attributeValue(NSAccessibilityValueAttribute);
1013     if ([value isKindOfClass:[NSNumber class]])
1014         return [value intValue] == 2;
1015     END_AX_OBJC_EXCEPTIONS
1016
1017     return false;
1018 }
1019
1020 bool AccessibilityUIElement::isExpanded() const
1021 {
1022     return boolAttributeValue(NSAccessibilityExpandedAttribute);
1023 }
1024
1025 bool AccessibilityUIElement::isChecked() const
1026 {
1027     // On the Mac, intValue()==1 if a a checkable control is checked.
1028     return intValue() == 1;
1029 }
1030
1031 JSRetainPtr<JSStringRef> AccessibilityUIElement::currentStateValue() const
1032 {
1033     return stringAttributeValue(NSAccessibilityARIACurrentAttribute);
1034 }
1035
1036 JSRetainPtr<JSStringRef> AccessibilityUIElement::sortDirection() const
1037 {
1038     return stringAttributeValue(NSAccessibilitySortDirectionAttribute);
1039 }
1040
1041 int AccessibilityUIElement::hierarchicalLevel() const
1042 {
1043     BEGIN_AX_OBJC_EXCEPTIONS
1044     auto value = attributeValue(NSAccessibilityDisclosureLevelAttribute);
1045     if ([value isKindOfClass:[NSNumber class]])
1046         return [value intValue];
1047     END_AX_OBJC_EXCEPTIONS
1048
1049     return 0;
1050 }
1051     
1052 JSRetainPtr<JSStringRef> AccessibilityUIElement::classList() const
1053 {
1054     BEGIN_AX_OBJC_EXCEPTIONS
1055     auto value = attributeValue(@"AXDOMClassList");
1056     if (![value isKindOfClass:[NSArray class]])
1057         return nullptr;
1058
1059     NSMutableString *classList = [NSMutableString string];
1060     NSInteger length = [value count];
1061     for (NSInteger k = 0; k < length; ++k) {
1062         [classList appendString:[value objectAtIndex:k]];
1063         if (k < length - 1)
1064             [classList appendString:@", "];
1065     }
1066
1067     return [classList createJSStringRef];
1068     END_AX_OBJC_EXCEPTIONS
1069
1070     return nullptr;
1071 }
1072
1073 JSRetainPtr<JSStringRef> AccessibilityUIElement::speakAs()
1074 {
1075     BEGIN_AX_OBJC_EXCEPTIONS
1076     auto value = attributeValue(@"AXDRTSpeechAttribute");
1077     if ([value isKindOfClass:[NSArray class]])
1078         return [[(NSArray *)value componentsJoinedByString:@", "] createJSStringRef];
1079     END_AX_OBJC_EXCEPTIONS
1080
1081     return nullptr;
1082 }
1083
1084 bool AccessibilityUIElement::ariaIsGrabbed() const
1085 {
1086     return boolAttributeValue(NSAccessibilityGrabbedAttribute);
1087 }
1088
1089 JSRetainPtr<JSStringRef> AccessibilityUIElement::ariaDropEffects() const
1090 {
1091     BEGIN_AX_OBJC_EXCEPTIONS
1092     auto value = attributeValue(NSAccessibilityDropEffectsAttribute);
1093     if (![value isKindOfClass:[NSArray class]])
1094         return nullptr;
1095
1096     NSMutableString *dropEffects = [NSMutableString string];
1097     NSInteger length = [value count];
1098     for (NSInteger k = 0; k < length; ++k) {
1099         [dropEffects appendString:[value objectAtIndex:k]];
1100         if (k < length - 1)
1101             [dropEffects appendString:@","];
1102     }
1103
1104     return [dropEffects createJSStringRef];
1105     END_AX_OBJC_EXCEPTIONS
1106
1107     return nullptr;
1108 }
1109
1110 // parameterized attributes
1111 int AccessibilityUIElement::lineForIndex(int index)
1112 {
1113     BEGIN_AX_OBJC_EXCEPTIONS
1114     auto value = attributeValueForParameter(NSAccessibilityLineForIndexParameterizedAttribute, @(index));
1115     if ([value isKindOfClass:[NSNumber class]])
1116         return [(NSNumber *)value intValue]; 
1117     END_AX_OBJC_EXCEPTIONS
1118
1119     return -1;
1120 }
1121
1122 JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForLine(int line)
1123 {
1124     BEGIN_AX_OBJC_EXCEPTIONS
1125     auto value = attributeValueForParameter(NSAccessibilityRangeForLineParameterizedAttribute, @(line));
1126     if ([value isKindOfClass:[NSValue class]])
1127         return [NSStringFromRange([value rangeValue]) createJSStringRef];
1128     END_AX_OBJC_EXCEPTIONS
1129
1130     return nullptr;
1131 }
1132
1133 JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForPosition(int x, int y)
1134 {
1135     BEGIN_AX_OBJC_EXCEPTIONS
1136     auto value = attributeValueForParameter(NSAccessibilityRangeForPositionParameterizedAttribute, [NSValue valueWithPoint:NSMakePoint(x, y)]);
1137     if ([value isKindOfClass:[NSValue class]])
1138         return [NSStringFromRange([value rangeValue]) createJSStringRef];
1139     END_AX_OBJC_EXCEPTIONS
1140
1141     return nullptr;
1142 }
1143
1144 JSRetainPtr<JSStringRef> AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
1145 {
1146     NSRange range = NSMakeRange(location, length);
1147     BEGIN_AX_OBJC_EXCEPTIONS
1148     auto value = attributeValueForParameter(NSAccessibilityBoundsForRangeParameterizedAttribute, [NSValue valueWithRange:range]);
1149     NSRect rect = NSMakeRect(0,0,0,0);
1150     if ([value isKindOfClass:[NSValue class]])
1151         rect = [value rectValue]; 
1152
1153     // don't return position information because it is platform dependent
1154     NSMutableString* boundsDescription = [NSMutableString stringWithFormat:@"{{%f, %f}, {%f, %f}}",-1.0f,-1.0f,rect.size.width,rect.size.height];
1155     return [boundsDescription createJSStringRef];
1156     END_AX_OBJC_EXCEPTIONS
1157
1158     return nullptr;
1159 }
1160
1161 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
1162 {
1163     NSRange range = NSMakeRange(location, length);
1164     BEGIN_AX_OBJC_EXCEPTIONS
1165     auto string = attributeValueForParameter(NSAccessibilityStringForRangeParameterizedAttribute, [NSValue valueWithRange:range]);
1166     if (![string isKindOfClass:[NSString class]])
1167         return nullptr;
1168
1169     return [string createJSStringRef];
1170     END_AX_OBJC_EXCEPTIONS
1171     
1172     return nullptr;
1173 }
1174
1175 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForRange(unsigned location, unsigned length)
1176 {
1177     NSRange range = NSMakeRange(location, length);
1178     BEGIN_AX_OBJC_EXCEPTIONS
1179     auto string = attributeValueForParameter(NSAccessibilityAttributedStringForRangeParameterizedAttribute, [NSValue valueWithRange:range]);
1180     if (![string isKindOfClass:[NSAttributedString class]])
1181         return nullptr;
1182
1183     NSString* stringWithAttrs = [string description];
1184     return [stringWithAttrs createJSStringRef];
1185     END_AX_OBJC_EXCEPTIONS
1186
1187     return nullptr;
1188 }
1189
1190 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
1191 {
1192     NSRange range = NSMakeRange(location, length);
1193     BEGIN_AX_OBJC_EXCEPTIONS
1194     auto string = attributeValueForParameter(NSAccessibilityAttributedStringForRangeParameterizedAttribute, [NSValue valueWithRange:range]);
1195     if (![string isKindOfClass:[NSAttributedString class]])
1196         return false;
1197
1198     NSDictionary* attrs = [string attributesAtIndex:0 effectiveRange:nil];
1199     BOOL misspelled = [[attrs objectForKey:NSAccessibilityMisspelledTextAttribute] boolValue];
1200 #if PLATFORM(MAC)
1201     if (misspelled)
1202         misspelled = [[attrs objectForKey:NSAccessibilityMarkedMisspelledTextAttribute] boolValue];
1203 #endif
1204     return misspelled;
1205     END_AX_OBJC_EXCEPTIONS
1206
1207     return false;
1208 }
1209
1210 unsigned AccessibilityUIElement::uiElementCountForSearchPredicate(JSContextRef context, AccessibilityUIElement *startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly)
1211 {
1212     BEGIN_AX_OBJC_EXCEPTIONS
1213     NSDictionary *parameterizedAttribute = searchPredicateParameterizedAttributeForSearchCriteria(context, startElement, isDirectionNext, UINT_MAX, searchKey, searchText, visibleOnly, immediateDescendantsOnly);
1214     auto value = attributeValueForParameter(@"AXUIElementCountForSearchPredicate", parameterizedAttribute);
1215     if ([value isKindOfClass:[NSNumber class]])
1216         return [value unsignedIntValue];
1217     END_AX_OBJC_EXCEPTIONS
1218     
1219     return 0;
1220 }
1221
1222 RefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef context, AccessibilityUIElement *startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly)
1223 {
1224     BEGIN_AX_OBJC_EXCEPTIONS
1225     NSDictionary *parameterizedAttribute = searchPredicateParameterizedAttributeForSearchCriteria(context, startElement, isDirectionNext, 1, searchKey, searchText, visibleOnly, immediateDescendantsOnly);
1226     auto searchResults = attributeValueForParameter(@"AXUIElementsForSearchPredicate", parameterizedAttribute);
1227     if ([searchResults isKindOfClass:[NSArray class]]) {
1228         if (id lastResult = [searchResults lastObject])
1229             return AccessibilityUIElement::create(lastResult);
1230     }
1231     END_AX_OBJC_EXCEPTIONS
1232
1233     return nullptr;
1234 }
1235
1236 JSRetainPtr<JSStringRef> AccessibilityUIElement::selectTextWithCriteria(JSContextRef context, JSStringRef ambiguityResolution, JSValueRef searchStrings, JSStringRef replacementString, JSStringRef activity)
1237 {
1238     BEGIN_AX_OBJC_EXCEPTIONS
1239     NSDictionary *parameterizedAttribute = selectTextParameterizedAttributeForCriteria(context, ambiguityResolution, searchStrings, replacementString, activity);
1240     auto result = attributeValueForParameter(@"AXSelectTextWithCriteria", parameterizedAttribute);
1241     if ([result isKindOfClass:[NSString class]])
1242         return [result.get() createJSStringRef];
1243     END_AX_OBJC_EXCEPTIONS
1244
1245     return nullptr;
1246 }
1247
1248 #if PLATFORM(MAC)
1249 JSValueRef AccessibilityUIElement::searchTextWithCriteria(JSContextRef context, JSValueRef searchStrings, JSStringRef startFrom, JSStringRef direction)
1250 {
1251     BEGIN_AX_OBJC_EXCEPTIONS
1252     NSDictionary *parameterizedAttribute = searchTextParameterizedAttributeForCriteria(context, searchStrings, startFrom, direction);
1253     auto result = attributeValueForParameter(@"AXSearchTextWithCriteria", parameterizedAttribute);
1254     if ([result isKindOfClass:[NSArray class]])
1255         return makeJSArray(makeVector<RefPtr<AccessibilityTextMarkerRange>>(result.get()));
1256     END_AX_OBJC_EXCEPTIONS
1257
1258     return nullptr;
1259 }
1260 #endif
1261
1262 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumnHeaders()
1263 {
1264     // not yet defined in AppKit... odd
1265     BEGIN_AX_OBJC_EXCEPTIONS
1266     auto columnHeaders = attributeValue(@"AXColumnHeaderUIElements");
1267     auto columnHeadersVector = makeVector<RefPtr<AccessibilityUIElement>>(columnHeaders.get());
1268     return descriptionOfElements(columnHeadersVector);
1269     END_AX_OBJC_EXCEPTIONS
1270
1271     return nullptr;
1272 }
1273
1274 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfRowHeaders()
1275 {
1276     BEGIN_AX_OBJC_EXCEPTIONS
1277     auto rowHeaders = attributeValue(@"AXRowHeaderUIElements");
1278     auto rowHeadersVector = makeVector<RefPtr<AccessibilityUIElement>>(rowHeaders.get());
1279     return descriptionOfElements(rowHeadersVector);
1280     END_AX_OBJC_EXCEPTIONS
1281
1282     return nullptr;
1283 }
1284
1285 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumns()
1286 {
1287     BEGIN_AX_OBJC_EXCEPTIONS
1288     auto columns = attributeValue(NSAccessibilityColumnsAttribute);
1289     auto columnsVector = makeVector<RefPtr<AccessibilityUIElement>>(columns.get());
1290     return descriptionOfElements(columnsVector);
1291     END_AX_OBJC_EXCEPTIONS
1292
1293     return nullptr;
1294 }
1295
1296 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfRows()
1297 {
1298     BEGIN_AX_OBJC_EXCEPTIONS
1299     auto rows = attributeValue(NSAccessibilityRowsAttribute);
1300     auto rowsVector = makeVector<RefPtr<AccessibilityUIElement>>(rows.get());
1301     return descriptionOfElements(rowsVector);
1302     END_AX_OBJC_EXCEPTIONS
1303
1304     return nullptr;
1305 }
1306
1307 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfVisibleCells()
1308 {
1309     BEGIN_AX_OBJC_EXCEPTIONS
1310     auto cells = attributeValue(@"AXVisibleCells");
1311     auto cellsVector = makeVector<RefPtr<AccessibilityUIElement>>(cells.get());
1312     return descriptionOfElements(cellsVector);
1313     END_AX_OBJC_EXCEPTIONS
1314
1315     return nullptr;
1316 }
1317
1318 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfHeader()
1319 {
1320     BEGIN_AX_OBJC_EXCEPTIONS
1321     auto header = attributeValue(NSAccessibilityHeaderAttribute);
1322     if (!header)
1323         return [@"" createJSStringRef];
1324
1325     Vector<RefPtr<AccessibilityUIElement>> headerVector;
1326     headerVector.append(AccessibilityUIElement::create(header.get()));
1327     return descriptionOfElements(headerVector);
1328     END_AX_OBJC_EXCEPTIONS
1329
1330     return nullptr;
1331 }
1332
1333 int AccessibilityUIElement::rowCount()
1334 {
1335     BEGIN_AX_OBJC_EXCEPTIONS
1336     return [m_element accessibilityArrayAttributeCount:NSAccessibilityRowsAttribute];
1337     END_AX_OBJC_EXCEPTIONS
1338     
1339     return 0;
1340 }
1341
1342 int AccessibilityUIElement::columnCount()
1343 {
1344     BEGIN_AX_OBJC_EXCEPTIONS
1345     return [m_element accessibilityArrayAttributeCount:NSAccessibilityColumnsAttribute];
1346     END_AX_OBJC_EXCEPTIONS
1347     
1348     return 0;
1349 }
1350
1351 int AccessibilityUIElement::indexInTable()
1352 {
1353     BEGIN_AX_OBJC_EXCEPTIONS
1354     auto indexNumber = attributeValue(NSAccessibilityIndexAttribute);
1355     if (indexNumber)
1356         return [indexNumber intValue];
1357     END_AX_OBJC_EXCEPTIONS
1358
1359     return -1;
1360 }
1361
1362 JSRetainPtr<JSStringRef> AccessibilityUIElement::rowIndexRange()
1363 {
1364     NSRange range = NSMakeRange(0, 0);
1365     BEGIN_AX_OBJC_EXCEPTIONS
1366     auto indexRange = attributeValue(@"AXRowIndexRange");
1367     if (indexRange)
1368         range = [indexRange rangeValue];
1369     NSMutableString *rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", static_cast<unsigned long>(range.location), static_cast<unsigned long>(range.length)];
1370     return [rangeDescription createJSStringRef];
1371     END_AX_OBJC_EXCEPTIONS
1372
1373     return nullptr;
1374 }
1375
1376 JSRetainPtr<JSStringRef> AccessibilityUIElement::columnIndexRange()
1377 {
1378     NSRange range = NSMakeRange(0, 0);
1379     BEGIN_AX_OBJC_EXCEPTIONS
1380     auto indexRange = attributeValue(@"AXColumnIndexRange");
1381     if (indexRange)
1382         range = [indexRange rangeValue];
1383     NSMutableString *rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", static_cast<unsigned long>(range.location), static_cast<unsigned long>(range.length)];
1384     return [rangeDescription createJSStringRef];
1385     END_AX_OBJC_EXCEPTIONS
1386
1387     return nullptr;
1388 }
1389
1390 RefPtr<AccessibilityUIElement> AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row)
1391 {
1392     NSArray *colRowArray = @[@(col), @(row)];
1393     BEGIN_AX_OBJC_EXCEPTIONS
1394     if (auto cell = attributeValueForParameter(@"AXCellForColumnAndRow", colRowArray))
1395         return AccessibilityUIElement::create(cell.get());
1396     END_AX_OBJC_EXCEPTIONS    
1397
1398     return nullptr;
1399 }
1400
1401 RefPtr<AccessibilityUIElement> AccessibilityUIElement::horizontalScrollbar() const
1402 {
1403     if (!m_element)
1404         return nullptr;
1405
1406     BEGIN_AX_OBJC_EXCEPTIONS
1407     if (id scrollbar = attributeValue(NSAccessibilityHorizontalScrollBarAttribute).get())
1408         return AccessibilityUIElement::create(scrollbar);
1409     END_AX_OBJC_EXCEPTIONS    
1410
1411     return nullptr;
1412 }
1413
1414 RefPtr<AccessibilityUIElement> AccessibilityUIElement::verticalScrollbar() const
1415 {
1416     if (!m_element)
1417         return nullptr;
1418
1419     BEGIN_AX_OBJC_EXCEPTIONS
1420     if (id scrollbar = attributeValue(NSAccessibilityVerticalScrollBarAttribute).get())
1421         return AccessibilityUIElement::create(scrollbar);
1422     END_AX_OBJC_EXCEPTIONS        
1423
1424     return nullptr;
1425 }
1426
1427 void AccessibilityUIElement::scrollToMakeVisible()
1428 {
1429     BEGIN_AX_OBJC_EXCEPTIONS
1430     [m_element accessibilityPerformAction:@"AXScrollToVisible"];
1431     END_AX_OBJC_EXCEPTIONS
1432 }
1433     
1434 void AccessibilityUIElement::scrollToGlobalPoint(int x, int y)
1435 {
1436     BEGIN_AX_OBJC_EXCEPTIONS
1437     [m_element _accessibilityScrollToGlobalPoint:NSMakePoint(x, y)];
1438     END_AX_OBJC_EXCEPTIONS
1439 }
1440
1441 void AccessibilityUIElement::scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height)
1442 {
1443     BEGIN_AX_OBJC_EXCEPTIONS
1444     [m_element _accessibilityScrollToMakeVisibleWithSubFocus:NSMakeRect(x, y, width, height)];
1445     END_AX_OBJC_EXCEPTIONS
1446 }
1447
1448 JSRetainPtr<JSStringRef> AccessibilityUIElement::selectedTextRange()
1449 {
1450     NSRange range = NSMakeRange(NSNotFound, 0);
1451     BEGIN_AX_OBJC_EXCEPTIONS
1452     auto indexRange = attributeValue(NSAccessibilitySelectedTextRangeAttribute);
1453     if (indexRange)
1454         range = [indexRange rangeValue];
1455     NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", static_cast<unsigned long>(range.location), static_cast<unsigned long>(range.length)];
1456     return [rangeDescription createJSStringRef];
1457     END_AX_OBJC_EXCEPTIONS
1458
1459     return nullptr;
1460 }
1461
1462 bool AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
1463 {
1464     NSRange textRange = NSMakeRange(location, length);
1465     NSValue *textRangeValue = [NSValue valueWithRange:textRange];
1466     setAttributeValue(m_element.get(), NSAccessibilitySelectedTextRangeAttribute, textRangeValue);
1467
1468     return true;
1469 }
1470
1471 void AccessibilityUIElement::dismiss()
1472 {
1473     BEGIN_AX_OBJC_EXCEPTIONS
1474     [m_element accessibilityPerformAction:@"AXDismissAction"];
1475     END_AX_OBJC_EXCEPTIONS
1476 }
1477
1478 bool AccessibilityUIElement::setSelectedTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
1479 {
1480     if (!markerRange)
1481         return false;
1482
1483     setAttributeValue(m_element.get(), NSAccessibilitySelectedTextMarkerRangeAttribute, markerRange->platformTextMarkerRange());
1484
1485     return true;
1486 }
1487
1488 void AccessibilityUIElement::increment()
1489 {
1490     BEGIN_AX_OBJC_EXCEPTIONS
1491     [m_element accessibilityPerformAction:@"AXSyncIncrementAction"];
1492     END_AX_OBJC_EXCEPTIONS
1493 }
1494
1495 void AccessibilityUIElement::decrement()
1496 {
1497     BEGIN_AX_OBJC_EXCEPTIONS
1498     [m_element accessibilityPerformAction:@"AXSyncDecrementAction"];
1499     END_AX_OBJC_EXCEPTIONS
1500 }
1501
1502 void AccessibilityUIElement::asyncIncrement()
1503 {
1504     BEGIN_AX_OBJC_EXCEPTIONS
1505     [m_element accessibilityPerformAction:NSAccessibilityIncrementAction];
1506     END_AX_OBJC_EXCEPTIONS
1507 }
1508
1509 void AccessibilityUIElement::asyncDecrement()
1510 {
1511     BEGIN_AX_OBJC_EXCEPTIONS
1512     [m_element accessibilityPerformAction:NSAccessibilityDecrementAction];
1513     END_AX_OBJC_EXCEPTIONS
1514 }
1515
1516 void AccessibilityUIElement::showMenu()
1517 {
1518     BEGIN_AX_OBJC_EXCEPTIONS
1519     [m_element accessibilityPerformAction:NSAccessibilityShowMenuAction];
1520     END_AX_OBJC_EXCEPTIONS
1521 }
1522
1523 void AccessibilityUIElement::press()
1524 {
1525     BEGIN_AX_OBJC_EXCEPTIONS
1526     [m_element accessibilityPerformAction:NSAccessibilityPressAction];
1527     END_AX_OBJC_EXCEPTIONS
1528 }
1529
1530 void AccessibilityUIElement::syncPress()
1531 {
1532     BEGIN_AX_OBJC_EXCEPTIONS
1533     [m_element accessibilityPerformAction:@"AXSyncPressAction"];
1534     END_AX_OBJC_EXCEPTIONS
1535 }
1536
1537 void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement* element) const
1538 {
1539     NSArray* array = element ? @[element->platformUIElement()] : @[];
1540     setAttributeValue(m_element.get(), NSAccessibilitySelectedChildrenAttribute, array);
1541 }
1542
1543 void AccessibilityUIElement::setSelectedChildAtIndex(unsigned index) const
1544 {
1545     RefPtr<AccessibilityUIElement> element = const_cast<AccessibilityUIElement*>(this)->childAtIndex(index);
1546     if (!element)
1547         return;
1548
1549     auto selectedChildren = attributeValue(NSAccessibilitySelectedChildrenAttribute);
1550     NSArray *array = @[element->platformUIElement()];
1551     if (selectedChildren)
1552         array = [selectedChildren arrayByAddingObjectsFromArray:array];
1553
1554     setAttributeValue(m_element.get(), NSAccessibilitySelectedChildrenAttribute, array, true);
1555 }
1556
1557 void AccessibilityUIElement::removeSelectionAtIndex(unsigned index) const
1558 {
1559     RefPtr<AccessibilityUIElement> element = const_cast<AccessibilityUIElement*>(this)->childAtIndex(index);
1560     if (!element)
1561         return;
1562
1563     auto selectedChildren = attributeValue(NSAccessibilitySelectedChildrenAttribute);
1564     if (!selectedChildren)
1565         return;
1566
1567     NSMutableArray *array = [NSMutableArray arrayWithArray:selectedChildren.get()];
1568     [array removeObject:element->platformUIElement()];
1569
1570     setAttributeValue(m_element.get(), NSAccessibilitySelectedChildrenAttribute, array, true);
1571 }
1572
1573 void AccessibilityUIElement::clearSelectedChildren() const
1574 {
1575 }
1576
1577 JSRetainPtr<JSStringRef> AccessibilityUIElement::accessibilityValue() const
1578 {
1579     return createJSString();
1580 }
1581
1582 JSRetainPtr<JSStringRef> AccessibilityUIElement::documentEncoding()
1583 {
1584     if (auto result = stringAttributeValue(@"AXDocumentEncoding"))
1585         return result;
1586
1587     return createJSString();
1588 }
1589
1590 JSRetainPtr<JSStringRef> AccessibilityUIElement::documentURI()
1591 {
1592     if (auto result = stringAttributeValue(@"AXDocumentURI"))
1593         return result;
1594
1595     return createJSString();
1596 }
1597
1598 JSRetainPtr<JSStringRef> AccessibilityUIElement::url()
1599 {
1600     BEGIN_AX_OBJC_EXCEPTIONS
1601     auto url = attributeValue(NSAccessibilityURLAttribute);
1602     if ([url isKindOfClass:[NSURL class]])
1603         return [[url absoluteString] createJSStringRef];
1604     END_AX_OBJC_EXCEPTIONS
1605     return nullptr;
1606 }
1607
1608 bool AccessibilityUIElement::addNotificationListener(JSValueRef functionCallback)
1609 {
1610     if (!functionCallback)
1611         return false;
1612  
1613     // Mac programmers should not be adding more than one notification listener per element.
1614     // Other platforms may be different.
1615     if (m_notificationHandler)
1616         return false;
1617
1618     m_notificationHandler = adoptNS([[AccessibilityNotificationHandler alloc] init]);
1619     [m_notificationHandler setPlatformElement:platformUIElement()];
1620     [m_notificationHandler setCallback:functionCallback];
1621     [m_notificationHandler startObserving];
1622
1623     return true;
1624 }
1625
1626 bool AccessibilityUIElement::removeNotificationListener()
1627 {
1628     // Mac programmers should not be trying to remove a listener that's already removed.
1629     ASSERT(m_notificationHandler);
1630
1631     [m_notificationHandler stopObserving];
1632     m_notificationHandler = nil;
1633     
1634     return true;
1635 }
1636
1637 bool AccessibilityUIElement::isFocusable() const
1638 {
1639     bool result = false;
1640     BEGIN_AX_OBJC_EXCEPTIONS
1641     result = [m_element accessibilityIsAttributeSettable:NSAccessibilityFocusedAttribute];
1642     END_AX_OBJC_EXCEPTIONS
1643     return result;
1644 }
1645
1646 bool AccessibilityUIElement::isSelectable() const
1647 {
1648     bool result = false;
1649     BEGIN_AX_OBJC_EXCEPTIONS
1650     result = [m_element accessibilityIsAttributeSettable:NSAccessibilitySelectedAttribute];
1651     END_AX_OBJC_EXCEPTIONS
1652     return result;
1653 }
1654
1655 bool AccessibilityUIElement::isMultiSelectable() const
1656 {
1657     BEGIN_AX_OBJC_EXCEPTIONS
1658     auto value = attributeValue(@"AXIsMultiSelectable");
1659     if ([value isKindOfClass:[NSNumber class]])
1660         return [value boolValue];
1661     END_AX_OBJC_EXCEPTIONS
1662     return false;
1663 }
1664
1665 bool AccessibilityUIElement::isVisible() const
1666 {
1667     return false;
1668 }
1669
1670 bool AccessibilityUIElement::isOnScreen() const
1671 {
1672     auto value = attributeValue(@"AXIsOnScreen");
1673     if ([value isKindOfClass:[NSNumber class]])
1674         return [value boolValue];
1675     return false;
1676 }
1677
1678 bool AccessibilityUIElement::isOffScreen() const
1679 {
1680     return false;
1681 }
1682
1683 bool AccessibilityUIElement::isCollapsed() const
1684 {
1685     return false;
1686 }
1687
1688 JSRetainPtr<JSStringRef> AccessibilityUIElement::embeddedImageDescription() const
1689 {
1690     BEGIN_AX_OBJC_EXCEPTIONS
1691     NSString *value = descriptionOfValue(attributeValue(@"AXEmbeddedImageDescription").get());
1692     return concatenateAttributeAndValue(@"AXEmbeddedImageDescription", value);
1693     END_AX_OBJC_EXCEPTIONS
1694     return nullptr;
1695 }
1696
1697 JSValueRef AccessibilityUIElement::imageOverlayElements() const
1698 {
1699     BEGIN_AX_OBJC_EXCEPTIONS
1700     return makeJSArray(makeVector<RefPtr<AccessibilityUIElement>>(attributeValue(@"AXImageOverlayElements").get()));
1701     END_AX_OBJC_EXCEPTIONS
1702
1703     return nullptr;
1704 }
1705
1706 bool AccessibilityUIElement::isIgnored() const
1707 {
1708     BOOL result = NO;
1709     BEGIN_AX_OBJC_EXCEPTIONS
1710     result = [m_element accessibilityIsIgnored];
1711     END_AX_OBJC_EXCEPTIONS
1712     return result;
1713 }
1714
1715 bool AccessibilityUIElement::isSingleLine() const
1716 {
1717     return false;
1718 }
1719
1720 bool AccessibilityUIElement::isMultiLine() const
1721 {
1722     return false;
1723 }
1724
1725 bool AccessibilityUIElement::hasPopup() const
1726 {
1727     return boolAttributeValue(@"AXHasPopup");
1728 }
1729
1730 JSRetainPtr<JSStringRef> AccessibilityUIElement::popupValue() const
1731 {
1732     if (auto result = stringAttributeValue(@"AXPopupValue"))
1733         return result;
1734
1735     return [@"false" createJSStringRef];
1736 }
1737
1738 bool AccessibilityUIElement::hasDocumentRoleAncestor() const
1739 {
1740     return boolAttributeValue(@"AXHasDocumentRoleAncestor");
1741 }
1742
1743 bool AccessibilityUIElement::hasWebApplicationAncestor() const
1744 {
1745     return boolAttributeValue(@"AXHasWebApplicationAncestor");
1746 }
1747
1748 bool AccessibilityUIElement::isInDescriptionListDetail() const
1749 {
1750     return boolAttributeValue(@"AXIsInDescriptionListDetail");
1751 }
1752
1753 bool AccessibilityUIElement::isInDescriptionListTerm() const
1754 {
1755     return boolAttributeValue(@"AXIsInDescriptionListTerm");
1756 }
1757
1758 bool AccessibilityUIElement::isInCell() const
1759 {
1760     return boolAttributeValue(@"AXIsInCell");
1761 }
1762
1763 void AccessibilityUIElement::takeFocus()
1764 {
1765     setAttributeValue(m_element.get(), NSAccessibilityFocusedAttribute, @YES);
1766 }
1767
1768 void AccessibilityUIElement::takeSelection()
1769 {
1770 }
1771
1772 void AccessibilityUIElement::addSelection()
1773 {
1774 }
1775
1776 void AccessibilityUIElement::removeSelection()
1777 {
1778 }
1779
1780 // Text markers
1781 RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::lineTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
1782 {
1783     if (!textMarker)
1784         return nullptr;
1785
1786     BEGIN_AX_OBJC_EXCEPTIONS
1787     auto textMarkerRange = attributeValueForParameter(@"AXLineTextMarkerRangeForTextMarker", textMarker->platformTextMarker());
1788     return AccessibilityTextMarkerRange::create(textMarkerRange.get());
1789     END_AX_OBJC_EXCEPTIONS
1790
1791     return nullptr;
1792 }
1793
1794 int AccessibilityUIElement::lineIndexForTextMarker(AccessibilityTextMarker* marker) const
1795 {
1796     if (!marker)
1797         return -1;
1798
1799     BEGIN_AX_OBJC_EXCEPTIONS
1800     return [attributeValueForParameter(@"AXLineForTextMarker", marker->platformTextMarker()) intValue];
1801     END_AX_OBJC_EXCEPTIONS
1802
1803     return -1;
1804 }
1805
1806 RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::misspellingTextMarkerRange(AccessibilityTextMarkerRange* start, bool forward)
1807 {
1808     BEGIN_AX_OBJC_EXCEPTIONS
1809     NSDictionary *parameters = misspellingSearchParameterizedAttributeForCriteria(start, forward);
1810     auto textMarkerRange = attributeValueForParameter(@"AXMisspellingTextMarkerRange", parameters);
1811     return AccessibilityTextMarkerRange::create(textMarkerRange.get());
1812     END_AX_OBJC_EXCEPTIONS
1813
1814     return nullptr;
1815 }
1816
1817 RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement* element)
1818 {
1819     BEGIN_AX_OBJC_EXCEPTIONS
1820     auto textMarkerRange = attributeValueForParameter(@"AXTextMarkerRangeForUIElement", element->platformUIElement());
1821     return AccessibilityTextMarkerRange::create(textMarkerRange.get());
1822     END_AX_OBJC_EXCEPTIONS
1823
1824     return nullptr;
1825 }
1826
1827 int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange* range)
1828 {
1829     if (!range)
1830         return 0;
1831
1832     BEGIN_AX_OBJC_EXCEPTIONS
1833     auto lengthValue = attributeValueForParameter(@"AXLengthForTextMarkerRange", range->platformTextMarkerRange());
1834     return [lengthValue intValue];
1835     END_AX_OBJC_EXCEPTIONS
1836
1837     return 0;
1838 }
1839
1840 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousTextMarker(AccessibilityTextMarker* textMarker)
1841 {
1842     if (!textMarker)
1843         return nullptr;
1844
1845     BEGIN_AX_OBJC_EXCEPTIONS
1846     auto previousMarker = attributeValueForParameter(@"AXPreviousTextMarkerForTextMarker", textMarker->platformTextMarker());
1847     return AccessibilityTextMarker::create(previousMarker.get());
1848     END_AX_OBJC_EXCEPTIONS
1849
1850     return nullptr;
1851 }
1852
1853 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextTextMarker(AccessibilityTextMarker* textMarker)
1854 {
1855     if (!textMarker)
1856         return nullptr;
1857
1858     BEGIN_AX_OBJC_EXCEPTIONS
1859     auto nextMarker = attributeValueForParameter(@"AXNextTextMarkerForTextMarker", textMarker->platformTextMarker());
1860     return AccessibilityTextMarker::create(nextMarker.get());
1861     END_AX_OBJC_EXCEPTIONS
1862
1863     return nullptr;
1864 }
1865
1866 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
1867 {
1868     if (!markerRange)
1869         return nullptr;
1870
1871     BEGIN_AX_OBJC_EXCEPTIONS
1872     auto textString = attributeValueForParameter(@"AXStringForTextMarkerRange", markerRange->platformTextMarkerRange());
1873     return [textString createJSStringRef];
1874     END_AX_OBJC_EXCEPTIONS
1875
1876     return nullptr;
1877 }
1878
1879 JSRetainPtr<JSStringRef> AccessibilityUIElement::rectsForTextMarkerRange(AccessibilityTextMarkerRange*, JSStringRef)
1880 {
1881     // Not implemented on macOS
1882     return nullptr;
1883 }
1884
1885 RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker)
1886 {
1887     BEGIN_AX_OBJC_EXCEPTIONS
1888     NSArray *textMarkers = @[startMarker->platformTextMarker(), endMarker->platformTextMarker()];
1889     auto textMarkerRange = attributeValueForParameter(@"AXTextMarkerRangeForTextMarkers", textMarkers);
1890     return AccessibilityTextMarkerRange::create(textMarkerRange.get());
1891     END_AX_OBJC_EXCEPTIONS
1892
1893     return nullptr;
1894 }
1895
1896 RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForRange(unsigned location, unsigned length)
1897 {
1898     BEGIN_AX_OBJC_EXCEPTIONS
1899     return AccessibilityTextMarkerRange::create(attributeValueForParameter(@"AXTextMarkerRangeForNSRange",
1900         [NSValue valueWithRange:NSMakeRange(location, length)]).get());
1901     END_AX_OBJC_EXCEPTIONS
1902
1903     return nullptr;
1904 }
1905
1906 RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::selectedTextMarkerRange()
1907 {
1908     BEGIN_AX_OBJC_EXCEPTIONS
1909     auto textMarkerRange = attributeValue(NSAccessibilitySelectedTextMarkerRangeAttribute);
1910     return AccessibilityTextMarkerRange::create(textMarkerRange.get());
1911     END_AX_OBJC_EXCEPTIONS
1912
1913     return nullptr;
1914 }
1915
1916 void AccessibilityUIElement::resetSelectedTextMarkerRange()
1917 {
1918     auto start = attributeValue(@"AXStartTextMarker");
1919     if (!start)
1920         return;
1921
1922     NSArray *textMarkers = @[start.get(), start.get()];
1923     auto textMarkerRange = attributeValueForParameter(@"AXTextMarkerRangeForUnorderedTextMarkers", textMarkers);
1924     if (!textMarkerRange)
1925         return;
1926
1927     setAttributeValue(m_element.get(), NSAccessibilitySelectedTextMarkerRangeAttribute, textMarkerRange.get(), true);
1928 }
1929
1930 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1931 {
1932     if (!range)
1933         return nullptr;
1934
1935     BEGIN_AX_OBJC_EXCEPTIONS
1936     auto textMarker = attributeValueForParameter(@"AXStartTextMarkerForTextMarkerRange", range->platformTextMarkerRange());
1937     return AccessibilityTextMarker::create(textMarker.get());
1938     END_AX_OBJC_EXCEPTIONS
1939
1940     return nullptr;
1941 }
1942
1943 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1944 {
1945     if (!range)
1946         return nullptr;
1947
1948     BEGIN_AX_OBJC_EXCEPTIONS
1949     auto textMarker = attributeValueForParameter(@"AXEndTextMarkerForTextMarkerRange", range->platformTextMarkerRange());
1950     return AccessibilityTextMarker::create(textMarker.get());
1951     END_AX_OBJC_EXCEPTIONS
1952
1953     return nullptr;
1954 }
1955
1956 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForBounds(int x, int y, int width, int height)
1957 {
1958     BEGIN_AX_OBJC_EXCEPTIONS
1959     auto textMarker = attributeValueForParameter(NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute,
1960         [NSValue valueWithRect:NSMakeRect(x, y, width, height)]);
1961     return AccessibilityTextMarker::create(textMarker.get());
1962     END_AX_OBJC_EXCEPTIONS
1963
1964     return nullptr;
1965 }
1966
1967 bool AccessibilityUIElement::replaceTextInRange(JSStringRef string, int location, int length)
1968 {
1969     bool result = false;
1970
1971     BEGIN_AX_OBJC_EXCEPTIONS
1972     AccessibilityUIElement::s_controller->executeOnAXThreadAndWait([text = [NSString stringWithJSStringRef:string], range = NSMakeRange(location, length), this, &result] {
1973         result = [m_element accessibilityReplaceRange:range withText:text];
1974     });
1975     END_AX_OBJC_EXCEPTIONS
1976
1977     return result;
1978 }
1979
1980 bool AccessibilityUIElement::insertText(JSStringRef text)
1981 {
1982     BEGIN_AX_OBJC_EXCEPTIONS
1983     return [m_element accessibilityInsertText:[NSString stringWithJSStringRef:text]];
1984     END_AX_OBJC_EXCEPTIONS
1985     return false;
1986 }
1987
1988 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForBounds(int x, int y, int width, int height)
1989 {
1990     BEGIN_AX_OBJC_EXCEPTIONS
1991     auto textMarker = attributeValueForParameter(NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute,
1992         [NSValue valueWithRect:NSMakeRect(x, y, width, height)]);
1993     return AccessibilityTextMarker::create(textMarker.get());
1994     END_AX_OBJC_EXCEPTIONS
1995
1996     return nullptr;
1997 }
1998
1999 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForPoint(int x, int y)
2000 {
2001     BEGIN_AX_OBJC_EXCEPTIONS
2002     auto textMarker = attributeValueForParameter(@"AXTextMarkerForPosition", [NSValue valueWithPoint:NSMakePoint(x, y)]);
2003     return AccessibilityTextMarker::create(textMarker.get());
2004     END_AX_OBJC_EXCEPTIONS
2005
2006     return nullptr;
2007 }
2008
2009 RefPtr<AccessibilityUIElement> AccessibilityUIElement::accessibilityElementForTextMarker(AccessibilityTextMarker* marker)
2010 {
2011     if (!marker)
2012         return nullptr;
2013
2014     BEGIN_AX_OBJC_EXCEPTIONS
2015     auto uiElement = attributeValueForParameter(@"AXUIElementForTextMarker", marker->platformTextMarker());
2016     if (uiElement)
2017         return AccessibilityUIElement::create(uiElement.get());
2018     END_AX_OBJC_EXCEPTIONS
2019
2020     return nullptr;
2021 }
2022
2023 static JSRetainPtr<JSStringRef> createJSStringRef(id string)
2024 {
2025     auto mutableString = adoptNS([[NSMutableString alloc] init]);
2026     id attributes = [string attributesAtIndex:0 effectiveRange:nil];
2027     id attributeEnumerationBlock = ^(NSDictionary<NSString *, id> *attrs, NSRange range, BOOL *stop) {
2028         BOOL misspelled = [[attrs objectForKey:NSAccessibilityMisspelledTextAttribute] boolValue];
2029         if (misspelled)
2030             misspelled = [[attrs objectForKey:NSAccessibilityMarkedMisspelledTextAttribute] boolValue];
2031         if (misspelled)
2032             [mutableString appendString:@"Misspelled, "];
2033         id font = [attributes objectForKey:(__bridge id)kAXFontTextAttribute];
2034         if (font)
2035             [mutableString appendFormat:@"%@ - %@, ", (__bridge id)kAXFontTextAttribute, font];
2036     };
2037     [string enumerateAttributesInRange:NSMakeRange(0, [string length]) options:(NSAttributedStringEnumerationOptions)0 usingBlock:attributeEnumerationBlock];
2038     [mutableString appendString:[string string]];
2039     return [mutableString createJSStringRef];
2040 }
2041
2042 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
2043 {
2044     if (!markerRange)
2045         return nullptr;
2046
2047     BEGIN_AX_OBJC_EXCEPTIONS
2048     auto string = attributeValueForParameter(@"AXAttributedStringForTextMarkerRange", markerRange->platformTextMarkerRange());
2049     if ([string isKindOfClass:[NSAttributedString class]])
2050         return createJSStringRef(string.get());
2051     END_AX_OBJC_EXCEPTIONS
2052
2053     return nil;
2054 }
2055
2056 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions(AccessibilityTextMarkerRange* markerRange, bool includeSpellCheck)
2057 {
2058     if (!markerRange || !markerRange->platformTextMarkerRange())
2059         return nullptr;
2060
2061     id parameter = nil;
2062     if (includeSpellCheck)
2063         parameter = @{ @"AXSpellCheck": includeSpellCheck ? @YES : @NO, @"AXTextMarkerRange": markerRange->platformTextMarkerRange() };
2064     else
2065         parameter = markerRange->platformTextMarkerRange();
2066
2067     BEGIN_AX_OBJC_EXCEPTIONS
2068     auto string = attributeValueForParameter(@"AXAttributedStringForTextMarkerRangeWithOptions", parameter);
2069     if ([string isKindOfClass:[NSAttributedString class]])
2070         return createJSStringRef(string.get());
2071     END_AX_OBJC_EXCEPTIONS
2072
2073     return nil;
2074 }
2075
2076 bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef attribute, AccessibilityTextMarkerRange* range)
2077 {
2078     if (!range)
2079         return false;
2080
2081     BEGIN_AX_OBJC_EXCEPTIONS
2082     auto string = attributeValueForParameter(@"AXAttributedStringForTextMarkerRange", range->platformTextMarkerRange());
2083     if (![string isKindOfClass:[NSAttributedString class]])
2084         return false;
2085
2086     NSDictionary* attrs = [string attributesAtIndex:0 effectiveRange:nil];
2087     if ([attrs objectForKey:[NSString stringWithJSStringRef:attribute]])
2088         return true;    
2089     END_AX_OBJC_EXCEPTIONS
2090
2091     return false;
2092 }
2093     
2094 int AccessibilityUIElement::indexForTextMarker(AccessibilityTextMarker* marker)
2095 {
2096     if (!marker)
2097         return -1;
2098
2099     BEGIN_AX_OBJC_EXCEPTIONS
2100     auto indexNumber = attributeValueForParameter(@"AXIndexForTextMarker", marker->platformTextMarker());
2101     return [indexNumber intValue];
2102     END_AX_OBJC_EXCEPTIONS
2103
2104     return -1;
2105 }
2106
2107 bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker* textMarker)
2108 {
2109     if (!textMarker)
2110         return false;
2111
2112     BEGIN_AX_OBJC_EXCEPTIONS
2113     auto value = attributeValueForParameter(@"AXTextMarkerIsValid", textMarker->platformTextMarker());
2114     return [value boolValue];
2115     END_AX_OBJC_EXCEPTIONS
2116
2117     return false;
2118 }
2119
2120 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForIndex(int textIndex)
2121 {
2122     BEGIN_AX_OBJC_EXCEPTIONS
2123     auto textMarker = attributeValueForParameter(@"AXTextMarkerForIndex", [NSNumber numberWithInteger:textIndex]);
2124     return AccessibilityTextMarker::create(textMarker.get());
2125     END_AX_OBJC_EXCEPTIONS
2126
2127     return nullptr;
2128 }
2129
2130 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarker()
2131 {
2132     BEGIN_AX_OBJC_EXCEPTIONS
2133     auto textMarker = attributeValue(@"AXStartTextMarker");
2134     return AccessibilityTextMarker::create(textMarker.get());
2135     END_AX_OBJC_EXCEPTIONS
2136
2137     return nullptr;
2138 }
2139
2140 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarker()
2141 {
2142     BEGIN_AX_OBJC_EXCEPTIONS
2143     auto textMarker = attributeValue(@"AXEndTextMarker");
2144     return AccessibilityTextMarker::create(textMarker.get());
2145     END_AX_OBJC_EXCEPTIONS
2146
2147     return nullptr;
2148 }
2149
2150 RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::leftWordTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
2151 {
2152     if (!textMarker)
2153         return nullptr;
2154
2155     BEGIN_AX_OBJC_EXCEPTIONS
2156     auto textMarkerRange = attributeValueForParameter(@"AXLeftWordTextMarkerRangeForTextMarker", textMarker->platformTextMarker());
2157     return AccessibilityTextMarkerRange::create(textMarkerRange.get());
2158     END_AX_OBJC_EXCEPTIONS
2159
2160     return nullptr;
2161 }
2162
2163 RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::rightWordTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
2164 {
2165     if (!textMarker)
2166         return nullptr;
2167
2168     BEGIN_AX_OBJC_EXCEPTIONS
2169     auto textMarkerRange = attributeValueForParameter(@"AXRightWordTextMarkerRangeForTextMarker", textMarker->platformTextMarker());
2170     return AccessibilityTextMarkerRange::create(textMarkerRange.get());
2171     END_AX_OBJC_EXCEPTIONS
2172
2173     return nullptr;
2174 }
2175
2176 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousWordStartTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
2177 {
2178     if (!textMarker)
2179         return nullptr;
2180
2181     BEGIN_AX_OBJC_EXCEPTIONS
2182     auto previousWordStartMarker = attributeValueForParameter(@"AXPreviousWordStartTextMarkerForTextMarker", textMarker->platformTextMarker());
2183     return AccessibilityTextMarker::create(previousWordStartMarker.get());
2184     END_AX_OBJC_EXCEPTIONS
2185
2186     return nullptr;
2187 }
2188
2189 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextWordEndTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
2190 {
2191     if (!textMarker)
2192         return nullptr;
2193
2194     BEGIN_AX_OBJC_EXCEPTIONS
2195     auto nextWordEndMarker = attributeValueForParameter(@"AXNextWordEndTextMarkerForTextMarker", textMarker->platformTextMarker());
2196     return AccessibilityTextMarker::create(nextWordEndMarker.get());
2197     END_AX_OBJC_EXCEPTIONS
2198
2199     return nullptr;
2200 }
2201
2202 RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::paragraphTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
2203 {
2204     if (!textMarker)
2205         return nullptr;
2206
2207     BEGIN_AX_OBJC_EXCEPTIONS
2208     auto textMarkerRange = attributeValueForParameter(@"AXParagraphTextMarkerRangeForTextMarker", textMarker->platformTextMarker());
2209     return AccessibilityTextMarkerRange::create(textMarkerRange.get());
2210     END_AX_OBJC_EXCEPTIONS
2211
2212     return nullptr;
2213 }
2214
2215 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousParagraphStartTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
2216 {
2217     if (!textMarker)
2218         return nullptr;
2219
2220     BEGIN_AX_OBJC_EXCEPTIONS
2221     auto previousParagraphStartMarker = attributeValueForParameter(@"AXPreviousParagraphStartTextMarkerForTextMarker", textMarker->platformTextMarker());
2222     return AccessibilityTextMarker::create(previousParagraphStartMarker.get());
2223     END_AX_OBJC_EXCEPTIONS
2224
2225     return nullptr;
2226 }
2227
2228 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextParagraphEndTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
2229 {
2230     if (!textMarker)
2231         return nullptr;
2232
2233     BEGIN_AX_OBJC_EXCEPTIONS
2234     auto nextParagraphEndMarker = attributeValueForParameter(@"AXNextParagraphEndTextMarkerForTextMarker", textMarker->platformTextMarker());
2235     return AccessibilityTextMarker::create(nextParagraphEndMarker.get());
2236     END_AX_OBJC_EXCEPTIONS
2237
2238     return nullptr;
2239 }
2240
2241 RefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::sentenceTextMarkerRangeForTextMarker(AccessibilityTextMarker* textMarker)
2242 {
2243     if (!textMarker)
2244         return nullptr;
2245
2246     BEGIN_AX_OBJC_EXCEPTIONS
2247     auto textMarkerRange = attributeValueForParameter(@"AXSentenceTextMarkerRangeForTextMarker", textMarker->platformTextMarker());
2248     return AccessibilityTextMarkerRange::create(textMarkerRange.get());
2249     END_AX_OBJC_EXCEPTIONS
2250
2251     return nullptr;
2252 }
2253
2254 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousSentenceStartTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
2255 {
2256     if (!textMarker)
2257         return nullptr;
2258
2259     BEGIN_AX_OBJC_EXCEPTIONS
2260     auto previousParagraphStartMarker = attributeValueForParameter(@"AXPreviousSentenceStartTextMarkerForTextMarker", textMarker->platformTextMarker());
2261     return AccessibilityTextMarker::create(previousParagraphStartMarker.get());
2262     END_AX_OBJC_EXCEPTIONS
2263
2264     return nullptr;
2265 }
2266
2267 RefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextSentenceEndTextMarkerForTextMarker(AccessibilityTextMarker* textMarker)
2268 {
2269     if (!textMarker)
2270         return nullptr;
2271
2272     BEGIN_AX_OBJC_EXCEPTIONS
2273     auto nextParagraphEndMarker = attributeValueForParameter(@"AXNextSentenceEndTextMarkerForTextMarker", textMarker->platformTextMarker());
2274     return AccessibilityTextMarker::create(nextParagraphEndMarker.get());
2275     END_AX_OBJC_EXCEPTIONS
2276
2277     return nullptr;
2278 }
2279
2280 static NSString *_convertMathMultiscriptPairsToString(NSArray *pairs)
2281 {
2282     __block NSMutableString *result = [NSMutableString string];
2283     [pairs enumerateObjectsUsingBlock:^(id pair, NSUInteger index, BOOL *stop) {
2284         for (NSString *key in pair) {
2285             auto element = AccessibilityUIElement::create([pair objectForKey:key]);
2286             auto subrole = element->attributeValue(NSAccessibilitySubroleAttribute);
2287             [result appendFormat:@"\t%lu. %@ = %@\n", (unsigned long)index, key, subrole.get()];
2288         }
2289     }];
2290
2291     return result;
2292 }
2293
2294 JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPostscriptsDescription() const
2295 {
2296     BEGIN_AX_OBJC_EXCEPTIONS
2297     auto pairs = attributeValue(@"AXMathPostscripts");
2298     return [_convertMathMultiscriptPairsToString(pairs.get()) createJSStringRef];
2299     END_AX_OBJC_EXCEPTIONS
2300
2301     return nullptr;
2302 }
2303
2304 JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPrescriptsDescription() const
2305 {
2306     BEGIN_AX_OBJC_EXCEPTIONS
2307     auto pairs = attributeValue(@"AXMathPrescripts");
2308     return [_convertMathMultiscriptPairsToString(pairs.get()) createJSStringRef];
2309     END_AX_OBJC_EXCEPTIONS
2310
2311     return nullptr;
2312 }
2313
2314 JSValueRef AccessibilityUIElement::mathRootRadicand() const
2315 {
2316     BEGIN_AX_OBJC_EXCEPTIONS
2317     return makeJSArray(makeVector<RefPtr<AccessibilityUIElement>>(attributeValue(@"AXMathRootRadicand").get()));
2318     END_AX_OBJC_EXCEPTIONS
2319
2320     return nullptr;
2321 }
2322
2323 JSRetainPtr<JSStringRef> AccessibilityUIElement::pathDescription() const
2324 {
2325     BEGIN_AX_OBJC_EXCEPTIONS
2326     NSMutableString *result = [NSMutableString stringWithString:@"\nStart Path\n"];
2327     auto bezierPath = attributeValue(NSAccessibilityPathAttribute);
2328
2329     NSUInteger elementCount = [bezierPath elementCount];
2330     NSPoint points[3];
2331     for (NSUInteger i = 0; i < elementCount; i++) {
2332         switch ([bezierPath elementAtIndex:i associatedPoints:points]) {
2333         case NSMoveToBezierPathElement:
2334             [result appendString:@"\tMove to point\n"];
2335             break;
2336
2337         case NSLineToBezierPathElement:
2338             [result appendString:@"\tLine to\n"];
2339             break;
2340
2341         case NSCurveToBezierPathElement:
2342             [result appendString:@"\tCurve to\n"];
2343             break;
2344
2345         case NSClosePathBezierPathElement:
2346             [result appendString:@"\tClose\n"];
2347             break;
2348         }
2349     }
2350
2351     return [result createJSStringRef];
2352     END_AX_OBJC_EXCEPTIONS
2353
2354     return nullptr;
2355 }
2356     
2357 JSRetainPtr<JSStringRef> AccessibilityUIElement::supportedActions() const
2358 {
2359     BEGIN_AX_OBJC_EXCEPTIONS
2360     NSArray *names = [m_element accessibilityActionNames];
2361     return [[names componentsJoinedByString:@","] createJSStringRef];
2362     END_AX_OBJC_EXCEPTIONS
2363     
2364     return nullptr;
2365 }
2366
2367 } // namespace WTR
2368
2369 #endif // HAVE(ACCESSIBILITY)