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