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