Allow multiple searchKeys to be passed to AXUIElementCopyParameterizedAttributeValue
[WebKit-https.git] / Tools / DumpRenderTree / mac / AccessibilityUIElementMac.mm
1 /*
2  * Copyright (C) 2008 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 "DumpRenderTree.h"
28 #import "AccessibilityCommonMac.h"
29 #import "AccessibilityNotificationHandler.h"
30 #import "AccessibilityUIElement.h"
31
32 #import <Foundation/Foundation.h>
33 #import <JavaScriptCore/JSRetainPtr.h>
34 #import <JavaScriptCore/JSStringRef.h>
35 #import <JavaScriptCore/JSStringRefCF.h>
36 #import <WebKit/WebFrame.h>
37 #import <WebKit/WebHTMLView.h>
38 #import <WebKit/WebTypesInternal.h>
39 #import <wtf/RetainPtr.h>
40 #import <wtf/Vector.h>
41
42
43 #ifndef NSAccessibilityOwnsAttribute
44 #define NSAccessibilityOwnsAttribute @"AXOwns"
45 #endif
46
47 #ifndef NSAccessibilityGrabbedAttribute
48 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
49 #endif
50
51 #ifndef NSAccessibilityDropEffectsAttribute
52 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
53 #endif
54
55 typedef void (*AXPostedNotificationCallback)(id element, NSString* notification, void* context);
56
57 @interface NSObject (WebKitAccessibilityAdditions)
58 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
59 - (NSUInteger)accessibilityIndexOfChild:(id)child;
60 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute;
61 @end
62
63 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
64     : m_element(element)
65     , m_notificationHandler(0)
66 {
67     // FIXME: ap@webkit.org says ObjC objects need to be CFRetained/CFRelease to be GC-compliant on the mac.
68     [m_element retain];
69 }
70
71 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
72     : m_element(other.m_element)
73     , m_notificationHandler(0)
74 {
75     [m_element retain];
76 }
77
78 AccessibilityUIElement::~AccessibilityUIElement()
79 {
80     // The notification handler should be nil because removeNotificationListener() should have been called in the test.
81     ASSERT(!m_notificationHandler);
82     [m_element release];
83 }
84
85 static NSString* descriptionOfValue(id valueObject, id focusedAccessibilityObject)
86 {
87     if (!valueObject)
88         return NULL;
89
90     if ([valueObject isKindOfClass:[NSArray class]])
91         return [NSString stringWithFormat:@"<array of size %lu>", static_cast<unsigned long>([(NSArray*)valueObject count])];
92
93     if ([valueObject isKindOfClass:[NSNumber class]])
94         return [(NSNumber*)valueObject stringValue];
95
96     if ([valueObject isKindOfClass:[NSValue class]]) {
97         NSString* type = [NSString stringWithCString:[valueObject objCType] encoding:NSASCIIStringEncoding];
98         NSValue* value = (NSValue*)valueObject;
99         if ([type rangeOfString:@"NSRect"].length > 0)
100             return [NSString stringWithFormat:@"NSRect: %@", NSStringFromRect([value rectValue])];
101         if ([type rangeOfString:@"NSPoint"].length > 0)
102             return [NSString stringWithFormat:@"NSPoint: %@", NSStringFromPoint([value pointValue])];
103         if ([type rangeOfString:@"NSSize"].length > 0)
104             return [NSString stringWithFormat:@"NSSize: %@", NSStringFromSize([value sizeValue])];
105         if ([type rangeOfString:@"NSRange"].length > 0)
106             return [NSString stringWithFormat:@"NSRange: %@", NSStringFromRange([value rangeValue])];
107     }
108
109     // Strip absolute URL paths
110     NSString* description = [valueObject description];
111     NSRange range = [description rangeOfString:@"LayoutTests"];
112     if (range.length)
113         return [description substringFromIndex:range.location];
114
115     // Strip pointer locations
116     if ([description rangeOfString:@"0x"].length) {
117         NSString* role = [focusedAccessibilityObject accessibilityAttributeValue:NSAccessibilityRoleAttribute];
118         NSString* title = [focusedAccessibilityObject accessibilityAttributeValue:NSAccessibilityTitleAttribute];
119         if ([title length])
120             return [NSString stringWithFormat:@"<%@: '%@'>", role, title];
121         return [NSString stringWithFormat:@"<%@>", role];
122     }
123     
124     return [valueObject description];
125 }
126
127 static NSString* attributesOfElement(id accessibilityObject)
128 {
129     NSArray* supportedAttributes = [accessibilityObject accessibilityAttributeNames];
130
131     NSMutableString* attributesString = [NSMutableString string];
132     for (NSUInteger i = 0; i < [supportedAttributes count]; ++i) {
133         NSString* attribute = [supportedAttributes objectAtIndex:i];
134         
135         // Right now, position provides useless and screen-specific information, so we do not
136         // want to include it for the sake of universally passing tests.
137         if ([attribute isEqualToString:@"AXPosition"])
138             continue;
139         
140         // accessibilityAttributeValue: can throw an if an attribute is not returned.
141         // For DumpRenderTree's purpose, we should ignore those exceptions
142         BEGIN_AX_OBJC_EXCEPTIONS
143         id valueObject = [accessibilityObject accessibilityAttributeValue:attribute];
144         NSString* value = descriptionOfValue(valueObject, accessibilityObject);
145         [attributesString appendFormat:@"%@: %@\n", attribute, value];
146         END_AX_OBJC_EXCEPTIONS
147     }
148     
149     return attributesString;
150 }
151
152 static JSStringRef concatenateAttributeAndValue(NSString* attribute, NSString* value)
153 {
154     Vector<UniChar> buffer([attribute length]);
155     [attribute getCharacters:buffer.data()];
156     buffer.append(':');
157     buffer.append(' ');
158
159     Vector<UniChar> valueBuffer([value length]);
160     [value getCharacters:valueBuffer.data()];
161     buffer.append(valueBuffer);
162
163     return JSStringCreateWithCharacters(buffer.data(), buffer.size());
164 }
165
166 static void convertNSArrayToVector(NSArray* array, Vector<AccessibilityUIElement>& elementVector)
167 {
168     NSUInteger count = [array count];
169     for (NSUInteger i = 0; i < count; ++i)
170         elementVector.append(AccessibilityUIElement([array objectAtIndex:i]));
171 }
172
173 static JSStringRef descriptionOfElements(Vector<AccessibilityUIElement>& elementVector)
174 {
175     NSMutableString* allElementString = [NSMutableString string];
176     size_t size = elementVector.size();
177     for (size_t i = 0; i < size; ++i) {
178         NSString* attributes = attributesOfElement(elementVector[i].platformUIElement());
179         [allElementString appendFormat:@"%@\n------------\n", attributes];
180     }
181     
182     return [allElementString createJSStringRef];
183 }
184
185 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elementVector)
186 {
187     BEGIN_AX_OBJC_EXCEPTIONS
188     NSArray* linkedElements = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
189     convertNSArrayToVector(linkedElements, elementVector);
190     END_AX_OBJC_EXCEPTIONS
191 }
192
193 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>& elementVector)
194 {
195     BEGIN_AX_OBJC_EXCEPTIONS
196     NSArray* linkElements = [m_element accessibilityAttributeValue:@"AXLinkUIElements"];
197     convertNSArrayToVector(linkElements, elementVector);
198     END_AX_OBJC_EXCEPTIONS
199 }
200
201 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& elementVector)
202 {
203     BEGIN_AX_OBJC_EXCEPTIONS
204     NSArray* children = [m_element accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
205     convertNSArrayToVector(children, elementVector);
206     END_AX_OBJC_EXCEPTIONS
207 }
208
209 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned location, unsigned length)
210 {
211     BEGIN_AX_OBJC_EXCEPTIONS
212     NSArray* children = [m_element accessibilityArrayAttributeValues:NSAccessibilityChildrenAttribute index:location maxCount:length];
213     convertNSArrayToVector(children, elementVector);
214     END_AX_OBJC_EXCEPTIONS
215 }
216
217 int AccessibilityUIElement::childrenCount()
218 {
219     Vector<AccessibilityUIElement> children;
220     getChildren(children);
221     
222     return children.size();
223 }
224
225 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
226 {
227     id element = [m_element accessibilityHitTest:NSMakePoint(x, y)];
228     if (!element)
229         return nil;
230     
231     return AccessibilityUIElement(element); 
232 }
233
234 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
235 {
236     return [m_element accessibilityIndexOfChild:element->platformUIElement()];
237 }
238
239 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
240 {
241     Vector<AccessibilityUIElement> children;
242     getChildrenWithRange(children, index, 1);
243
244     if (children.size() == 1)
245         return children[0];
246     return 0;
247 }
248
249 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
250 {
251     BEGIN_AX_OBJC_EXCEPTIONS
252     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
253     if (index < [objects count])
254         return [objects objectAtIndex:index];
255     END_AX_OBJC_EXCEPTIONS
256     
257     return 0;
258 }
259
260 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
261 {
262     BEGIN_AX_OBJC_EXCEPTIONS
263     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityOwnsAttribute];
264     if (index < [objects count])
265         return [objects objectAtIndex:index];
266     END_AX_OBJC_EXCEPTIONS
267     
268     return 0;
269 }
270
271 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
272 {
273     BEGIN_AX_OBJC_EXCEPTIONS
274     NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
275     if (index < [objects count])
276         return [objects objectAtIndex:index];
277     END_AX_OBJC_EXCEPTIONS
278     
279     return 0;
280 }
281
282 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
283 {
284     BEGIN_AX_OBJC_EXCEPTIONS
285     NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilityDisclosedRowsAttribute];
286     if (index < [rows count])
287         return [rows objectAtIndex:index];
288     END_AX_OBJC_EXCEPTIONS
289
290     return 0;
291 }
292
293 AccessibilityUIElement AccessibilityUIElement::selectedChildAtIndex(unsigned index) const
294 {
295     BEGIN_AX_OBJC_EXCEPTIONS
296     NSArray* array = [m_element accessibilityAttributeValue:NSAccessibilitySelectedChildrenAttribute];
297     if (index < [array count])
298         return [array objectAtIndex:index];
299     END_AX_OBJC_EXCEPTIONS
300     
301     return 0;
302 }
303
304 unsigned AccessibilityUIElement::selectedChildrenCount() const
305 {
306     BEGIN_AX_OBJC_EXCEPTIONS
307     return [m_element accessibilityArrayAttributeCount:NSAccessibilitySelectedChildrenAttribute];
308     END_AX_OBJC_EXCEPTIONS
309
310     return 0;
311 }
312
313 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
314 {
315     BEGIN_AX_OBJC_EXCEPTIONS
316     NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilitySelectedRowsAttribute];
317     if (index < [rows count])
318         return [rows objectAtIndex:index];
319     END_AX_OBJC_EXCEPTIONS
320     
321     return 0;
322 }
323
324 AccessibilityUIElement AccessibilityUIElement::rowAtIndex(unsigned index)
325 {
326     BEGIN_AX_OBJC_EXCEPTIONS
327     NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilityRowsAttribute];
328     if (index < [rows count])
329         return [rows objectAtIndex:index];
330     END_AX_OBJC_EXCEPTIONS
331     
332     return 0;
333 }
334
335 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
336 {
337     BEGIN_AX_OBJC_EXCEPTIONS
338     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityTitleUIElementAttribute];
339     if (accessibilityObject)
340         return AccessibilityUIElement(accessibilityObject);
341     END_AX_OBJC_EXCEPTIONS
342     
343     return 0;
344 }
345
346 AccessibilityUIElement AccessibilityUIElement::parentElement()
347 {
348     BEGIN_AX_OBJC_EXCEPTIONS
349     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityParentAttribute];
350     if (accessibilityObject)
351         return AccessibilityUIElement(accessibilityObject);
352     END_AX_OBJC_EXCEPTIONS
353     
354     return 0;
355 }
356
357 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
358 {
359     BEGIN_AX_OBJC_EXCEPTIONS
360     id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityDisclosedByRowAttribute];
361     if (accessibilityObject)
362         return AccessibilityUIElement(accessibilityObject);
363     END_AX_OBJC_EXCEPTIONS
364     
365     return 0;
366 }
367
368 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
369 {
370     Vector<AccessibilityUIElement> linkedElements;
371     getLinkedUIElements(linkedElements);
372     return descriptionOfElements(linkedElements);
373 }
374
375 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
376 {
377     Vector<AccessibilityUIElement> linkElements;
378     getDocumentLinks(linkElements);
379     return descriptionOfElements(linkElements);
380 }
381
382 JSStringRef AccessibilityUIElement::attributesOfChildren()
383 {
384     Vector<AccessibilityUIElement> children;
385     getChildren(children);
386     return descriptionOfElements(children);
387 }
388
389 JSStringRef AccessibilityUIElement::allAttributes()
390 {
391     NSString* attributes = attributesOfElement(m_element);
392     return [attributes createJSStringRef];
393 }
394
395 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
396 {
397     BEGIN_AX_OBJC_EXCEPTIONS
398     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
399     if ([value isKindOfClass:[NSString class]])
400         return [value createJSStringRef];
401     END_AX_OBJC_EXCEPTIONS
402
403     return 0;
404 }
405
406 AccessibilityUIElement AccessibilityUIElement::uiElementAttributeValue(JSStringRef attribute) const
407 {
408     BEGIN_AX_OBJC_EXCEPTIONS
409     id uiElement = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
410     return AccessibilityUIElement(uiElement);
411     END_AX_OBJC_EXCEPTIONS
412     
413     return 0;
414 }
415
416
417 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
418 {
419     BEGIN_AX_OBJC_EXCEPTIONS
420     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
421     if ([value isKindOfClass:[NSNumber class]])
422         return [value doubleValue];
423     END_AX_OBJC_EXCEPTIONS
424     
425     return 0;
426 }
427
428 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
429 {
430     BEGIN_AX_OBJC_EXCEPTIONS
431     id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
432     if ([value isKindOfClass:[NSNumber class]])
433         return [value boolValue];
434     END_AX_OBJC_EXCEPTIONS
435     
436     return false;
437 }
438
439 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
440 {
441     BEGIN_AX_OBJC_EXCEPTIONS
442     return [m_element accessibilityIsAttributeSettable:[NSString stringWithJSStringRef:attribute]];
443     END_AX_OBJC_EXCEPTIONS
444     
445     return false;
446 }
447
448 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
449 {
450     BEGIN_AX_OBJC_EXCEPTIONS
451     return [[m_element accessibilityAttributeNames] containsObject:[NSString stringWithJSStringRef:attribute]];
452     END_AX_OBJC_EXCEPTIONS
453     
454     return false;
455 }
456
457 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
458 {
459     NSArray* supportedParameterizedAttributes = [m_element accessibilityParameterizedAttributeNames];
460     
461     NSMutableString* attributesString = [NSMutableString string];
462     for (NSUInteger i = 0; i < [supportedParameterizedAttributes count]; ++i) {
463         [attributesString appendFormat:@"%@\n", [supportedParameterizedAttributes objectAtIndex:i]];
464     }
465     
466     return [attributesString createJSStringRef];
467 }
468
469 JSStringRef AccessibilityUIElement::role()
470 {
471     BEGIN_AX_OBJC_EXCEPTIONS
472     NSString *role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityRoleAttribute], m_element);
473     return concatenateAttributeAndValue(@"AXRole", role);
474     END_AX_OBJC_EXCEPTIONS
475     
476     return 0;
477 }
478
479 JSStringRef AccessibilityUIElement::subrole()
480 {
481     BEGIN_AX_OBJC_EXCEPTIONS
482     NSString* role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilitySubroleAttribute], m_element);
483     return concatenateAttributeAndValue(@"AXSubrole", role);
484     END_AX_OBJC_EXCEPTIONS
485
486     return 0;
487 }
488
489 JSStringRef AccessibilityUIElement::roleDescription()
490 {
491     BEGIN_AX_OBJC_EXCEPTIONS
492     NSString* role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute], m_element);
493     return concatenateAttributeAndValue(@"AXRoleDescription", role);
494     END_AX_OBJC_EXCEPTIONS
495     
496     return 0;
497 }
498
499 JSStringRef AccessibilityUIElement::title()
500 {
501     BEGIN_AX_OBJC_EXCEPTIONS
502     NSString* title = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityTitleAttribute], m_element);
503     return concatenateAttributeAndValue(@"AXTitle", title);
504     END_AX_OBJC_EXCEPTIONS
505
506     return 0;
507 }
508
509 JSStringRef AccessibilityUIElement::description()
510 {
511     BEGIN_AX_OBJC_EXCEPTIONS
512     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityDescriptionAttribute], m_element);
513     return concatenateAttributeAndValue(@"AXDescription", description);
514     END_AX_OBJC_EXCEPTIONS
515
516     return 0;
517 }
518
519 JSStringRef AccessibilityUIElement::orientation() const
520 {
521     BEGIN_AX_OBJC_EXCEPTIONS
522     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityOrientationAttribute], m_element);
523     return concatenateAttributeAndValue(@"AXOrientation", description);    
524     END_AX_OBJC_EXCEPTIONS
525
526     return 0;
527 }
528
529 JSStringRef AccessibilityUIElement::stringValue()
530 {
531     BEGIN_AX_OBJC_EXCEPTIONS
532     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityValueAttribute], m_element);
533     return concatenateAttributeAndValue(@"AXValue", description);
534     END_AX_OBJC_EXCEPTIONS
535
536     return 0;
537 }
538
539 JSStringRef AccessibilityUIElement::language()
540 {
541     BEGIN_AX_OBJC_EXCEPTIONS
542     id description = descriptionOfValue([m_element accessibilityAttributeValue:@"AXLanguage"], m_element);
543     return concatenateAttributeAndValue(@"AXLanguage", description);
544     END_AX_OBJC_EXCEPTIONS
545
546     return 0;
547 }
548
549 JSStringRef AccessibilityUIElement::helpText() const
550 {
551     BEGIN_AX_OBJC_EXCEPTIONS
552     id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityHelpAttribute], m_element);
553     return concatenateAttributeAndValue(@"AXHelp", description);
554     END_AX_OBJC_EXCEPTIONS
555     
556     return 0;
557 }
558
559 double AccessibilityUIElement::x()
560 {
561     BEGIN_AX_OBJC_EXCEPTIONS
562     NSValue* positionValue = [m_element accessibilityAttributeValue:NSAccessibilityPositionAttribute];
563     return static_cast<double>([positionValue pointValue].x);    
564     END_AX_OBJC_EXCEPTIONS
565     
566     return 0.0f;
567 }
568
569 double AccessibilityUIElement::y()
570 {
571     BEGIN_AX_OBJC_EXCEPTIONS
572     NSValue* positionValue = [m_element accessibilityAttributeValue:NSAccessibilityPositionAttribute];
573     return static_cast<double>([positionValue pointValue].y);    
574     END_AX_OBJC_EXCEPTIONS
575     
576     return 0.0f;
577 }
578
579 double AccessibilityUIElement::width()
580 {
581     BEGIN_AX_OBJC_EXCEPTIONS
582     NSValue* sizeValue = [m_element accessibilityAttributeValue:NSAccessibilitySizeAttribute];
583     return static_cast<double>([sizeValue sizeValue].width);
584     END_AX_OBJC_EXCEPTIONS
585     
586     return 0.0f;
587 }
588
589 double AccessibilityUIElement::height()
590 {
591     BEGIN_AX_OBJC_EXCEPTIONS
592     NSValue* sizeValue = [m_element accessibilityAttributeValue:NSAccessibilitySizeAttribute];
593     return static_cast<double>([sizeValue sizeValue].height);
594     END_AX_OBJC_EXCEPTIONS
595     
596     return 0.0f;
597 }
598
599 double AccessibilityUIElement::clickPointX()
600 {
601     BEGIN_AX_OBJC_EXCEPTIONS
602     NSValue* positionValue = [m_element accessibilityAttributeValue:@"AXClickPoint"];
603     return static_cast<double>([positionValue pointValue].x);        
604     END_AX_OBJC_EXCEPTIONS
605     
606     return 0.0f;
607 }
608
609 double AccessibilityUIElement::clickPointY()
610 {
611     BEGIN_AX_OBJC_EXCEPTIONS
612     NSValue* positionValue = [m_element accessibilityAttributeValue:@"AXClickPoint"];
613     return static_cast<double>([positionValue pointValue].y);
614     END_AX_OBJC_EXCEPTIONS
615     
616     return 0.0f;
617 }
618
619 double AccessibilityUIElement::intValue() const
620 {
621     BEGIN_AX_OBJC_EXCEPTIONS
622     id value = [m_element accessibilityAttributeValue:NSAccessibilityValueAttribute];
623     if ([value isKindOfClass:[NSNumber class]])
624         return [(NSNumber*)value doubleValue]; 
625     END_AX_OBJC_EXCEPTIONS
626
627     return 0.0f;
628 }
629
630 double AccessibilityUIElement::minValue()
631 {
632     BEGIN_AX_OBJC_EXCEPTIONS
633     id value = [m_element accessibilityAttributeValue:NSAccessibilityMinValueAttribute];
634     if ([value isKindOfClass:[NSNumber class]])
635         return [(NSNumber*)value doubleValue]; 
636     END_AX_OBJC_EXCEPTIONS
637
638     return 0.0f;
639 }
640
641 double AccessibilityUIElement::maxValue()
642 {
643     BEGIN_AX_OBJC_EXCEPTIONS
644     id value = [m_element accessibilityAttributeValue:NSAccessibilityMaxValueAttribute];
645     if ([value isKindOfClass:[NSNumber class]])
646         return [(NSNumber*)value doubleValue]; 
647     END_AX_OBJC_EXCEPTIONS
648
649     return 0.0;
650 }
651
652 JSStringRef AccessibilityUIElement::valueDescription()
653 {
654     BEGIN_AX_OBJC_EXCEPTIONS
655     NSString* valueDescription = [m_element accessibilityAttributeValue:NSAccessibilityValueDescriptionAttribute];
656     if ([valueDescription isKindOfClass:[NSString class]])
657          return [valueDescription createJSStringRef];
658
659     END_AX_OBJC_EXCEPTIONS
660     return 0;
661 }
662
663 int AccessibilityUIElement::insertionPointLineNumber()
664 {
665     BEGIN_AX_OBJC_EXCEPTIONS
666     id value = [m_element accessibilityAttributeValue:NSAccessibilityInsertionPointLineNumberAttribute];
667     if ([value isKindOfClass:[NSNumber class]])
668         return [(NSNumber *)value intValue]; 
669     END_AX_OBJC_EXCEPTIONS
670     
671     return -1;
672 }
673
674 bool AccessibilityUIElement::isPressActionSupported()
675 {
676     BEGIN_AX_OBJC_EXCEPTIONS
677     NSArray* actions = [m_element accessibilityActionNames];
678     return [actions containsObject:NSAccessibilityPressAction];
679     END_AX_OBJC_EXCEPTIONS
680     
681     return false;
682 }
683
684 bool AccessibilityUIElement::isIncrementActionSupported()
685 {
686     BEGIN_AX_OBJC_EXCEPTIONS
687     NSArray* actions = [m_element accessibilityActionNames];
688     return [actions containsObject:NSAccessibilityIncrementAction];
689     END_AX_OBJC_EXCEPTIONS
690     
691     return false;
692 }
693
694 bool AccessibilityUIElement::isDecrementActionSupported()
695 {
696     BEGIN_AX_OBJC_EXCEPTIONS
697     NSArray* actions = [m_element accessibilityActionNames];
698     return [actions containsObject:NSAccessibilityDecrementAction];
699     END_AX_OBJC_EXCEPTIONS
700     
701     return false;
702 }
703
704 bool AccessibilityUIElement::isEnabled()
705 {
706     BEGIN_AX_OBJC_EXCEPTIONS
707     id value = [m_element accessibilityAttributeValue:NSAccessibilityEnabledAttribute];
708     if ([value isKindOfClass:[NSNumber class]])
709         return [value boolValue];
710     END_AX_OBJC_EXCEPTIONS
711     
712     return false;
713 }
714
715 bool AccessibilityUIElement::isRequired() const
716 {
717     BEGIN_AX_OBJC_EXCEPTIONS
718     id value = [m_element accessibilityAttributeValue:@"AXRequired"];
719     if ([value isKindOfClass:[NSNumber class]])
720         return [value boolValue];
721     END_AX_OBJC_EXCEPTIONS
722     
723     return false;
724 }
725
726 bool AccessibilityUIElement::isFocused() const
727 {
728     // FIXME: implement
729     return false;
730 }
731
732 bool AccessibilityUIElement::isSelected() const
733 {
734     BEGIN_AX_OBJC_EXCEPTIONS
735     id value = [m_element accessibilityAttributeValue:NSAccessibilitySelectedAttribute];
736     if ([value isKindOfClass:[NSNumber class]])
737         return [value boolValue];
738     END_AX_OBJC_EXCEPTIONS
739     
740     return false;
741 }
742
743 bool AccessibilityUIElement::isExpanded() const
744 {
745     BEGIN_AX_OBJC_EXCEPTIONS
746     id value = [m_element accessibilityAttributeValue:NSAccessibilityExpandedAttribute];
747     if ([value isKindOfClass:[NSNumber class]])
748         return [value boolValue];
749     END_AX_OBJC_EXCEPTIONS
750     
751     return false;
752 }
753
754 bool AccessibilityUIElement::isChecked() const
755 {
756     // On the Mac, intValue()==1 if a a checkable control is checked.
757     return intValue() == 1;
758 }
759
760 int AccessibilityUIElement::hierarchicalLevel() const
761 {
762     BEGIN_AX_OBJC_EXCEPTIONS
763     id value = [m_element accessibilityAttributeValue:NSAccessibilityDisclosureLevelAttribute];
764     if ([value isKindOfClass:[NSNumber class]])
765         return [value intValue];
766     END_AX_OBJC_EXCEPTIONS
767
768     return 0;
769 }
770
771 JSStringRef AccessibilityUIElement::speak()
772 {
773     BEGIN_AX_OBJC_EXCEPTIONS
774     id value = [m_element accessibilityAttributeValue:@"AXDRTSpeechAttribute"];
775     if ([value isKindOfClass:[NSString class]])
776         return [value createJSStringRef];
777     END_AX_OBJC_EXCEPTIONS
778         
779     return 0;
780 }
781
782 bool AccessibilityUIElement::ariaIsGrabbed() const
783 {
784     BEGIN_AX_OBJC_EXCEPTIONS
785     id value = [m_element accessibilityAttributeValue:NSAccessibilityGrabbedAttribute];
786     if ([value isKindOfClass:[NSNumber class]])
787         return [value boolValue];
788     END_AX_OBJC_EXCEPTIONS
789
790     return false;
791 }
792
793 JSStringRef AccessibilityUIElement::ariaDropEffects() const
794 {
795     BEGIN_AX_OBJC_EXCEPTIONS
796     id value = [m_element accessibilityAttributeValue:NSAccessibilityDropEffectsAttribute];
797     if (![value isKindOfClass:[NSArray class]])
798         return 0;
799
800     NSMutableString* dropEffects = [NSMutableString string];
801     NSInteger length = [value count];
802     for (NSInteger k = 0; k < length; ++k) {
803         [dropEffects appendString:[value objectAtIndex:k]];
804         if (k < length - 1)
805             [dropEffects appendString:@","];
806     }
807     
808     return [dropEffects createJSStringRef];
809     END_AX_OBJC_EXCEPTIONS
810     
811     return 0;
812 }
813
814 // parameterized attributes
815 int AccessibilityUIElement::lineForIndex(int index)
816 {
817     BEGIN_AX_OBJC_EXCEPTIONS
818     id value = [m_element accessibilityAttributeValue:NSAccessibilityLineForIndexParameterizedAttribute forParameter:[NSNumber numberWithInt:index]];
819     if ([value isKindOfClass:[NSNumber class]])
820         return [(NSNumber *)value intValue]; 
821     END_AX_OBJC_EXCEPTIONS
822
823     return -1;
824 }
825
826 JSStringRef AccessibilityUIElement::rangeForLine(int line)
827 {
828     BEGIN_AX_OBJC_EXCEPTIONS
829     id value = [m_element accessibilityAttributeValue:NSAccessibilityRangeForLineParameterizedAttribute forParameter:[NSNumber numberWithInt:line]];
830     if ([value isKindOfClass:[NSValue class]])
831         return [NSStringFromRange([value rangeValue]) createJSStringRef];
832     END_AX_OBJC_EXCEPTIONS
833     
834     return 0;
835 }
836
837 JSStringRef AccessibilityUIElement::rangeForPosition(int x, int y)
838 {
839     BEGIN_AX_OBJC_EXCEPTIONS
840     id value = [m_element accessibilityAttributeValue:NSAccessibilityRangeForPositionParameterizedAttribute forParameter:[NSValue valueWithPoint:NSMakePoint(x, y)]];
841     if ([value isKindOfClass:[NSValue class]])
842         return [NSStringFromRange([value rangeValue]) createJSStringRef];
843     END_AX_OBJC_EXCEPTIONS
844     
845     return 0;
846 }
847
848
849 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
850 {
851     NSRange range = NSMakeRange(location, length);
852     BEGIN_AX_OBJC_EXCEPTIONS
853     id value = [m_element accessibilityAttributeValue:NSAccessibilityBoundsForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
854     NSRect rect = NSMakeRect(0,0,0,0);
855     if ([value isKindOfClass:[NSValue class]])
856         rect = [value rectValue]; 
857     
858     // don't return position information because it is platform dependent
859     NSMutableString* boundsDescription = [NSMutableString stringWithFormat:@"{{%f, %f}, {%f, %f}}",-1.0f,-1.0f,rect.size.width,rect.size.height];
860     return [boundsDescription createJSStringRef];
861     END_AX_OBJC_EXCEPTIONS
862     
863     return 0;
864 }
865
866 JSStringRef AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
867 {
868     NSRange range = NSMakeRange(location, length);
869     BEGIN_AX_OBJC_EXCEPTIONS
870     id string = [m_element accessibilityAttributeValue:NSAccessibilityStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
871     if (![string isKindOfClass:[NSString class]])
872         return 0;
873     
874     return [string createJSStringRef];
875     END_AX_OBJC_EXCEPTIONS
876     
877     return 0;
878 }
879
880 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned location, unsigned length)
881 {
882     NSRange range = NSMakeRange(location, length);
883     BEGIN_AX_OBJC_EXCEPTIONS
884     NSAttributedString* string = [m_element accessibilityAttributeValue:NSAccessibilityAttributedStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
885     if (![string isKindOfClass:[NSAttributedString class]])
886         return 0;
887     
888     NSString* stringWithAttrs = [string description];
889     return [stringWithAttrs createJSStringRef];
890     END_AX_OBJC_EXCEPTIONS
891     
892     return 0;
893 }
894
895 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
896 {
897     NSRange range = NSMakeRange(location, length);
898     BEGIN_AX_OBJC_EXCEPTIONS
899     NSAttributedString* string = [m_element accessibilityAttributeValue:NSAccessibilityAttributedStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
900     if (![string isKindOfClass:[NSAttributedString class]])
901         return false;
902
903     NSDictionary* attrs = [string attributesAtIndex:0 effectiveRange:nil];
904     if([[attrs objectForKey:NSAccessibilityMisspelledTextAttribute] boolValue])
905         return true;    
906     END_AX_OBJC_EXCEPTIONS
907     
908     return false;
909 }
910
911 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText)
912 {
913     BEGIN_AX_OBJC_EXCEPTIONS
914     NSMutableDictionary* parameter = [NSMutableDictionary dictionary];
915     [parameter setObject:(isDirectionNext) ? @"AXDirectionNext" : @"AXDirectionPrevious" forKey:@"AXDirection"];
916     [parameter setObject:[NSNumber numberWithInt:1] forKey:@"AXResultsLimit"];
917     if (startElement && startElement->platformUIElement())
918         [parameter setObject:(id)startElement->platformUIElement() forKey:@"AXStartElement"];
919     if (searchKey) {
920         if (JSValueIsString(context, searchKey)) {
921             NSString *searchKeyParameter = nil;
922             JSStringRef singleSearchKey = JSValueToStringCopy(context, searchKey, 0);
923             if (singleSearchKey) {
924                 searchKeyParameter = [NSString stringWithJSStringRef:singleSearchKey];
925                 JSStringRelease(singleSearchKey);
926                 if (searchKeyParameter)
927                     [parameter setObject:searchKeyParameter forKey:@"AXSearchKey"];
928             }
929         }
930         else if (JSValueIsObject(context, searchKey)) {
931             NSMutableArray *searchKeyParameter = nil;
932             JSObjectRef array = const_cast<JSObjectRef>(searchKey);
933             unsigned arrayLength = 0;
934             JSRetainPtr<JSStringRef> arrayLengthString(Adopt, JSStringCreateWithUTF8CString("length"));
935             JSValueRef arrayLengthValue = JSObjectGetProperty(context, array, arrayLengthString.get(), 0);
936             if (arrayLengthValue && JSValueIsNumber(context, arrayLengthValue))
937                 arrayLength = static_cast<unsigned>(JSValueToNumber(context, arrayLengthValue, 0));
938             
939             for (unsigned i = 0; i < arrayLength; ++i) {
940                 JSValueRef exception = 0;
941                 JSValueRef value = JSObjectGetPropertyAtIndex(context, array, i, &exception);
942                 if (exception)
943                     break;
944                 JSStringRef singleSearchKey = JSValueToStringCopy(context, value, &exception);
945                 if (exception)
946                     break;
947                 if (singleSearchKey) {
948                     if (!searchKeyParameter)
949                         searchKeyParameter = [NSMutableArray array];
950                     [searchKeyParameter addObject:[NSString stringWithJSStringRef:singleSearchKey]];
951                     JSStringRelease(singleSearchKey);
952                 }
953             }
954             if (searchKeyParameter)
955                 [parameter setObject:searchKeyParameter forKey:@"AXSearchKey"];
956         }
957     }
958     if (searchText && JSStringGetLength(searchText))
959         [parameter setObject:[NSString stringWithJSStringRef:searchText] forKey:@"AXSearchText"];
960     
961     id uiElement = [[m_element accessibilityAttributeValue:@"AXUIElementsForSearchPredicate" forParameter:parameter] lastObject];
962     return AccessibilityUIElement(uiElement);
963     END_AX_OBJC_EXCEPTIONS
964     
965     return 0;
966 }
967
968 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
969 {
970     // not yet defined in AppKit... odd
971     BEGIN_AX_OBJC_EXCEPTIONS
972     NSArray* columnHeadersArray = [m_element accessibilityAttributeValue:@"AXColumnHeaderUIElements"];
973     Vector<AccessibilityUIElement> columnHeadersVector;
974     convertNSArrayToVector(columnHeadersArray, columnHeadersVector);
975     return descriptionOfElements(columnHeadersVector);
976     END_AX_OBJC_EXCEPTIONS
977     
978     return 0;
979 }
980
981 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
982 {
983     BEGIN_AX_OBJC_EXCEPTIONS
984     NSArray* rowHeadersArray = [m_element accessibilityAttributeValue:@"AXRowHeaderUIElements"];
985     Vector<AccessibilityUIElement> rowHeadersVector;
986     convertNSArrayToVector(rowHeadersArray, rowHeadersVector);
987     return descriptionOfElements(rowHeadersVector);
988     END_AX_OBJC_EXCEPTIONS
989     
990     return 0;
991 }
992
993 JSStringRef AccessibilityUIElement::attributesOfColumns()
994 {
995     BEGIN_AX_OBJC_EXCEPTIONS
996     NSArray* columnsArray = [m_element accessibilityAttributeValue:NSAccessibilityColumnsAttribute];
997     Vector<AccessibilityUIElement> columnsVector;
998     convertNSArrayToVector(columnsArray, columnsVector);
999     return descriptionOfElements(columnsVector);
1000     END_AX_OBJC_EXCEPTIONS
1001     
1002     return 0;
1003 }
1004
1005 JSStringRef AccessibilityUIElement::attributesOfRows()
1006 {
1007     BEGIN_AX_OBJC_EXCEPTIONS
1008     NSArray* rowsArray = [m_element accessibilityAttributeValue:NSAccessibilityRowsAttribute];
1009     Vector<AccessibilityUIElement> rowsVector;
1010     convertNSArrayToVector(rowsArray, rowsVector);
1011     return descriptionOfElements(rowsVector);
1012     END_AX_OBJC_EXCEPTIONS
1013     
1014     return 0;
1015 }
1016
1017 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
1018 {
1019     BEGIN_AX_OBJC_EXCEPTIONS
1020     NSArray* cellsArray = [m_element accessibilityAttributeValue:@"AXVisibleCells"];
1021     Vector<AccessibilityUIElement> cellsVector;
1022     convertNSArrayToVector(cellsArray, cellsVector);
1023     return descriptionOfElements(cellsVector);
1024     END_AX_OBJC_EXCEPTIONS
1025     
1026     return 0;
1027 }
1028
1029 JSStringRef AccessibilityUIElement::attributesOfHeader()
1030 {
1031     BEGIN_AX_OBJC_EXCEPTIONS
1032     id headerObject = [m_element accessibilityAttributeValue:NSAccessibilityHeaderAttribute];
1033     if (!headerObject)
1034         return [@"" createJSStringRef];
1035     
1036     Vector<AccessibilityUIElement> headerVector;
1037     headerVector.append(headerObject);
1038     return descriptionOfElements(headerVector);
1039     END_AX_OBJC_EXCEPTIONS
1040     
1041     return 0;
1042 }
1043
1044 int AccessibilityUIElement::rowCount()
1045 {
1046     BEGIN_AX_OBJC_EXCEPTIONS
1047     return [m_element accessibilityArrayAttributeCount:NSAccessibilityRowsAttribute];
1048     END_AX_OBJC_EXCEPTIONS
1049     
1050     return 0;
1051 }
1052
1053 int AccessibilityUIElement::columnCount()
1054 {
1055     BEGIN_AX_OBJC_EXCEPTIONS
1056     return [m_element accessibilityArrayAttributeCount:NSAccessibilityColumnsAttribute];
1057     END_AX_OBJC_EXCEPTIONS
1058     
1059     return 0;
1060 }
1061
1062 int AccessibilityUIElement::indexInTable()
1063 {
1064     BEGIN_AX_OBJC_EXCEPTIONS
1065     NSNumber* indexNumber = [m_element accessibilityAttributeValue:NSAccessibilityIndexAttribute];
1066     if (indexNumber)
1067         return [indexNumber intValue];
1068     END_AX_OBJC_EXCEPTIONS
1069
1070     return -1;
1071 }
1072
1073 JSStringRef AccessibilityUIElement::rowIndexRange()
1074 {
1075     NSRange range = NSMakeRange(0, 0);
1076     BEGIN_AX_OBJC_EXCEPTIONS
1077     NSValue* indexRange = [m_element accessibilityAttributeValue:@"AXRowIndexRange"];
1078     if (indexRange)
1079         range = [indexRange rangeValue];
1080     NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", static_cast<unsigned long>(range.location), static_cast<unsigned long>(range.length)];
1081     return [rangeDescription createJSStringRef];
1082     END_AX_OBJC_EXCEPTIONS
1083     
1084     return 0;
1085 }
1086
1087 JSStringRef AccessibilityUIElement::columnIndexRange()
1088 {
1089     NSRange range = NSMakeRange(0, 0);
1090     BEGIN_AX_OBJC_EXCEPTIONS
1091     NSNumber* indexRange = [m_element accessibilityAttributeValue:@"AXColumnIndexRange"];
1092     if (indexRange)
1093         range = [indexRange rangeValue];
1094     NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}",static_cast<unsigned long>(range.location), static_cast<unsigned long>(range.length)];
1095     return [rangeDescription createJSStringRef];    
1096     END_AX_OBJC_EXCEPTIONS
1097     
1098     return 0;
1099 }
1100
1101 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row)
1102 {
1103     NSArray *colRowArray = [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:col], [NSNumber numberWithUnsignedInt:row], nil];
1104     BEGIN_AX_OBJC_EXCEPTIONS
1105     return [m_element accessibilityAttributeValue:@"AXCellForColumnAndRow" forParameter:colRowArray];
1106     END_AX_OBJC_EXCEPTIONS    
1107
1108     return 0;
1109 }
1110
1111 AccessibilityUIElement AccessibilityUIElement::horizontalScrollbar() const
1112 {
1113     BEGIN_AX_OBJC_EXCEPTIONS
1114     return AccessibilityUIElement([m_element accessibilityAttributeValue:NSAccessibilityHorizontalScrollBarAttribute]);
1115     END_AX_OBJC_EXCEPTIONS    
1116     
1117     return 0;
1118 }
1119
1120 AccessibilityUIElement AccessibilityUIElement::verticalScrollbar() const
1121 {
1122     BEGIN_AX_OBJC_EXCEPTIONS
1123     return AccessibilityUIElement([m_element accessibilityAttributeValue:NSAccessibilityVerticalScrollBarAttribute]);
1124     END_AX_OBJC_EXCEPTIONS        
1125
1126     return 0;
1127 }
1128
1129 JSStringRef AccessibilityUIElement::selectedTextRange()
1130 {
1131     NSRange range = NSMakeRange(NSNotFound, 0);
1132     BEGIN_AX_OBJC_EXCEPTIONS
1133     NSValue *indexRange = [m_element accessibilityAttributeValue:NSAccessibilitySelectedTextRangeAttribute];
1134     if (indexRange)
1135         range = [indexRange rangeValue];
1136     NSMutableString *rangeDescription = [NSMutableString stringWithFormat:@"{%lu, %lu}", static_cast<unsigned long>(range.location), static_cast<unsigned long>(range.length)];
1137     return [rangeDescription createJSStringRef];    
1138     END_AX_OBJC_EXCEPTIONS
1139     
1140     return 0;
1141 }
1142
1143 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
1144 {
1145     NSRange textRange = NSMakeRange(location, length);
1146     NSValue *textRangeValue = [NSValue valueWithRange:textRange];
1147     BEGIN_AX_OBJC_EXCEPTIONS
1148     [m_element accessibilitySetValue:textRangeValue forAttribute:NSAccessibilitySelectedTextRangeAttribute];
1149     END_AX_OBJC_EXCEPTIONS
1150 }
1151
1152 void AccessibilityUIElement::increment()
1153 {
1154     BEGIN_AX_OBJC_EXCEPTIONS
1155     [m_element accessibilityPerformAction:NSAccessibilityIncrementAction];
1156     END_AX_OBJC_EXCEPTIONS
1157 }
1158
1159 void AccessibilityUIElement::decrement()
1160 {
1161     BEGIN_AX_OBJC_EXCEPTIONS
1162     [m_element accessibilityPerformAction:NSAccessibilityDecrementAction];
1163     END_AX_OBJC_EXCEPTIONS
1164 }
1165
1166 void AccessibilityUIElement::showMenu()
1167 {
1168     BEGIN_AX_OBJC_EXCEPTIONS
1169     [m_element accessibilityPerformAction:NSAccessibilityShowMenuAction];
1170     END_AX_OBJC_EXCEPTIONS
1171 }
1172
1173 void AccessibilityUIElement::press()
1174 {
1175     BEGIN_AX_OBJC_EXCEPTIONS
1176     [m_element accessibilityPerformAction:NSAccessibilityPressAction];
1177     END_AX_OBJC_EXCEPTIONS
1178 }
1179
1180 void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement* element) const
1181 {
1182     BEGIN_AX_OBJC_EXCEPTIONS
1183     NSArray* array = [NSArray arrayWithObject:element->platformUIElement()];
1184     [m_element accessibilitySetValue:array forAttribute:NSAccessibilitySelectedChildrenAttribute];
1185     END_AX_OBJC_EXCEPTIONS    
1186 }
1187
1188 JSStringRef AccessibilityUIElement::accessibilityValue() const
1189 {
1190     // FIXME: implement
1191     return JSStringCreateWithCharacters(0, 0);
1192 }
1193
1194 JSStringRef AccessibilityUIElement::documentEncoding()
1195 {
1196     return JSStringCreateWithCharacters(0, 0);
1197 }
1198
1199 JSStringRef AccessibilityUIElement::documentURI()
1200 {
1201     return JSStringCreateWithCharacters(0, 0);
1202 }
1203
1204 JSStringRef AccessibilityUIElement::url()
1205 {
1206     BEGIN_AX_OBJC_EXCEPTIONS
1207     NSURL *url = [m_element accessibilityAttributeValue:NSAccessibilityURLAttribute];
1208     return [[url absoluteString] createJSStringRef];    
1209     END_AX_OBJC_EXCEPTIONS
1210     
1211     return nil;
1212 }
1213
1214 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
1215 {
1216     if (!functionCallback)
1217         return false;
1218  
1219     // Mac programmers should not be adding more than one notification listener per element.
1220     // Other platforms may be different.
1221     if (m_notificationHandler)
1222         return false;
1223     m_notificationHandler = [[AccessibilityNotificationHandler alloc] init];
1224     [m_notificationHandler setPlatformElement:platformUIElement()];
1225     [m_notificationHandler setCallback:functionCallback];
1226     [m_notificationHandler startObserving];
1227
1228     return true;
1229 }
1230
1231 void AccessibilityUIElement::removeNotificationListener()
1232 {
1233     // Mac programmers should not be trying to remove a listener that's already removed.
1234     ASSERT(m_notificationHandler);
1235
1236     [m_notificationHandler release];
1237     m_notificationHandler = nil;
1238 }
1239
1240 bool AccessibilityUIElement::isFocusable() const
1241 {
1242     bool result = false;
1243     BEGIN_AX_OBJC_EXCEPTIONS
1244     result = [m_element accessibilityIsAttributeSettable:NSAccessibilityFocusedAttribute];
1245     END_AX_OBJC_EXCEPTIONS
1246     
1247     return result;
1248 }
1249
1250 bool AccessibilityUIElement::isSelectable() const
1251 {
1252     // FIXME: implement
1253     return false;
1254 }
1255
1256 bool AccessibilityUIElement::isMultiSelectable() const
1257 {
1258     // FIXME: implement
1259     return false;
1260 }
1261
1262 bool AccessibilityUIElement::isSelectedOptionActive() const
1263 {
1264     // FIXME: implement
1265     return false;
1266 }
1267
1268 bool AccessibilityUIElement::isVisible() const
1269 {
1270     // FIXME: implement
1271     return false;
1272 }
1273
1274 bool AccessibilityUIElement::isOffScreen() const
1275 {
1276     // FIXME: implement
1277     return false;
1278 }
1279
1280 bool AccessibilityUIElement::isCollapsed() const
1281 {
1282     // FIXME: implement
1283     return false;
1284 }
1285
1286 bool AccessibilityUIElement::isIgnored() const
1287 {
1288     BOOL result = NO;
1289     BEGIN_AX_OBJC_EXCEPTIONS
1290     result = [m_element accessibilityIsIgnored];
1291     END_AX_OBJC_EXCEPTIONS
1292     return result;
1293 }
1294
1295 bool AccessibilityUIElement::hasPopup() const
1296 {
1297     BEGIN_AX_OBJC_EXCEPTIONS
1298     id value = [m_element accessibilityAttributeValue:@"AXHasPopup"];
1299     if ([value isKindOfClass:[NSNumber class]])
1300         return [value boolValue];
1301     END_AX_OBJC_EXCEPTIONS
1302
1303     return false;
1304 }
1305
1306 void AccessibilityUIElement::takeFocus()
1307 {
1308     // FIXME: implement
1309 }
1310
1311 void AccessibilityUIElement::takeSelection()
1312 {
1313     // FIXME: implement
1314 }
1315
1316 void AccessibilityUIElement::addSelection()
1317 {
1318     // FIXME: implement
1319 }
1320
1321 void AccessibilityUIElement::removeSelection()
1322 {
1323     // FIXME: implement
1324 }
1325
1326 #if SUPPORTS_AX_TEXTMARKERS
1327
1328 // Text markers
1329 AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement* element)
1330 {
1331     BEGIN_AX_OBJC_EXCEPTIONS
1332     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXTextMarkerRangeForUIElement" forParameter:element->platformUIElement()];
1333     return AccessibilityTextMarkerRange(textMarkerRange);
1334     END_AX_OBJC_EXCEPTIONS
1335     
1336     return 0;
1337 }
1338
1339 int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange* range)
1340 {
1341     BEGIN_AX_OBJC_EXCEPTIONS
1342     NSNumber* lengthValue = [m_element accessibilityAttributeValue:@"AXLengthForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1343     return [lengthValue intValue];
1344     END_AX_OBJC_EXCEPTIONS
1345     
1346     return 0;
1347 }
1348
1349 bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef attribute, AccessibilityTextMarkerRange* range)
1350 {
1351     BEGIN_AX_OBJC_EXCEPTIONS
1352     NSAttributedString* string = [m_element accessibilityAttributeValue:@"AXAttributedStringForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1353     if (![string isKindOfClass:[NSAttributedString class]])
1354         return false;
1355     
1356     NSDictionary* attrs = [string attributesAtIndex:0 effectiveRange:nil];
1357     if ([attrs objectForKey:[NSString stringWithJSStringRef:attribute]])
1358         return true;    
1359     END_AX_OBJC_EXCEPTIONS
1360     
1361     return false;
1362 }
1363
1364 int AccessibilityUIElement::indexForTextMarker(AccessibilityTextMarker* marker)
1365 {
1366     BEGIN_AX_OBJC_EXCEPTIONS
1367     NSNumber* indexNumber = [m_element accessibilityAttributeValue:@"AXIndexForTextMarker" forParameter:(id)marker->platformTextMarker()];
1368     return [indexNumber intValue];
1369     END_AX_OBJC_EXCEPTIONS
1370     
1371     return -1;
1372 }
1373
1374 AccessibilityTextMarker AccessibilityUIElement::textMarkerForIndex(int textIndex)
1375 {
1376     BEGIN_AX_OBJC_EXCEPTIONS
1377     id textMarker = [m_element accessibilityAttributeValue:@"AXTextMarkerForIndex" forParameter:[NSNumber numberWithInteger:textIndex]];
1378     return AccessibilityTextMarker(textMarker);
1379     END_AX_OBJC_EXCEPTIONS
1380     
1381     return 0;
1382 }
1383
1384 bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker* textMarker)
1385 {
1386     BEGIN_AX_OBJC_EXCEPTIONS
1387     NSNumber* validNumber = [m_element accessibilityAttributeValue:@"AXTextMarkerIsValid" forParameter:(id)textMarker->platformTextMarker()];
1388     return [validNumber boolValue];
1389     END_AX_OBJC_EXCEPTIONS
1390
1391     return false;
1392 }
1393
1394 AccessibilityTextMarker AccessibilityUIElement::previousTextMarker(AccessibilityTextMarker* textMarker)
1395 {
1396     BEGIN_AX_OBJC_EXCEPTIONS
1397     id previousMarker = [m_element accessibilityAttributeValue:@"AXPreviousTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1398     return AccessibilityTextMarker(previousMarker);
1399     END_AX_OBJC_EXCEPTIONS
1400     
1401     return 0;
1402 }
1403
1404 AccessibilityTextMarker AccessibilityUIElement::nextTextMarker(AccessibilityTextMarker* textMarker)
1405 {
1406     BEGIN_AX_OBJC_EXCEPTIONS
1407     id nextMarker = [m_element accessibilityAttributeValue:@"AXNextTextMarkerForTextMarker" forParameter:(id)textMarker->platformTextMarker()];
1408     return AccessibilityTextMarker(nextMarker);
1409     END_AX_OBJC_EXCEPTIONS
1410     
1411     return 0;
1412 }
1413
1414 JSStringRef AccessibilityUIElement::stringForTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
1415 {
1416     BEGIN_AX_OBJC_EXCEPTIONS
1417     id textString = [m_element accessibilityAttributeValue:@"AXStringForTextMarkerRange" forParameter:(id)markerRange->platformTextMarkerRange()];
1418     return [textString createJSStringRef];
1419     END_AX_OBJC_EXCEPTIONS
1420     
1421     return 0;
1422 }
1423
1424 AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker)
1425 {
1426     BEGIN_AX_OBJC_EXCEPTIONS
1427     NSArray* textMarkers = [NSArray arrayWithObjects:(id)startMarker->platformTextMarker(), (id)endMarker->platformTextMarker(), nil];
1428     id textMarkerRange = [m_element accessibilityAttributeValue:@"AXTextMarkerRangeForUnorderedTextMarkers" forParameter:textMarkers];
1429     return AccessibilityTextMarkerRange(textMarkerRange);
1430     END_AX_OBJC_EXCEPTIONS
1431     
1432     return 0;
1433 }
1434
1435 AccessibilityTextMarker AccessibilityUIElement::startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1436 {
1437     BEGIN_AX_OBJC_EXCEPTIONS
1438     id textMarker = [m_element accessibilityAttributeValue:@"AXStartTextMarkerForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1439     return AccessibilityTextMarker(textMarker);
1440     END_AX_OBJC_EXCEPTIONS
1441     
1442     return 0;    
1443 }
1444
1445 AccessibilityTextMarker AccessibilityUIElement::endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1446 {
1447     BEGIN_AX_OBJC_EXCEPTIONS
1448     id textMarker = [m_element accessibilityAttributeValue:@"AXEndTextMarkerForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1449     return AccessibilityTextMarker(textMarker);
1450     END_AX_OBJC_EXCEPTIONS
1451     
1452     return 0;    
1453 }
1454
1455 AccessibilityTextMarker AccessibilityUIElement::textMarkerForPoint(int x, int y)
1456 {
1457     BEGIN_AX_OBJC_EXCEPTIONS
1458     id textMarker = [m_element accessibilityAttributeValue:@"AXTextMarkerForPosition" forParameter:[NSValue valueWithPoint:NSMakePoint(x, y)]];
1459     return AccessibilityTextMarker(textMarker);
1460     END_AX_OBJC_EXCEPTIONS
1461     
1462     return 0;    
1463 }
1464
1465 AccessibilityUIElement AccessibilityUIElement::accessibilityElementForTextMarker(AccessibilityTextMarker* marker)
1466 {
1467     BEGIN_AX_OBJC_EXCEPTIONS
1468     id uiElement = [m_element accessibilityAttributeValue:@"AXUIElementForTextMarker" forParameter:(id)marker->platformTextMarker()];
1469     return AccessibilityUIElement(uiElement);
1470     END_AX_OBJC_EXCEPTIONS
1471     
1472     return 0;  
1473 }
1474
1475 #endif // SUPPORTS_AX_TEXTMARKERS
1476
1477 JSStringRef AccessibilityUIElement::supportedActions()
1478 {
1479     BEGIN_AX_OBJC_EXCEPTIONS
1480     NSArray *names = [m_element accessibilityActionNames];
1481     return [[names componentsJoinedByString:@","] createJSStringRef];
1482     END_AX_OBJC_EXCEPTIONS
1483
1484     return 0;
1485 }
1486
1487 void AccessibilityUIElement::scrollToMakeVisible()
1488 {
1489     BEGIN_AX_OBJC_EXCEPTIONS
1490     [m_element accessibilityPerformAction:@"AXScrollToVisible"];
1491     END_AX_OBJC_EXCEPTIONS
1492 }
1493
1494 void AccessibilityUIElement::scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height)
1495 {
1496     // FIXME: implement
1497 }
1498
1499 void AccessibilityUIElement::scrollToGlobalPoint(int x, int y)
1500 {
1501     // FIXME: implement
1502 }