[atk] Replace deprecated call to atk_document_get_locale() in DumpRenderTree
[WebKit-https.git] / Tools / WebKitTestRunner / InjectedBundle / atk / AccessibilityUIElementAtk.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2012 Igalia S.L.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "AccessibilityUIElement.h"
29
30 #if HAVE(ACCESSIBILITY)
31
32 #include "InjectedBundle.h"
33 #include "InjectedBundlePage.h"
34 #include "NotImplemented.h"
35 #include <JavaScriptCore/JSStringRef.h>
36 #include <atk/atk.h>
37 #include <wtf/Assertions.h>
38 #include <wtf/gobject/GOwnPtr.h>
39 #include <wtf/gobject/GRefPtr.h>
40 #include <wtf/text/CString.h>
41 #include <wtf/text/WTFString.h>
42 #include <wtf/unicode/CharacterNames.h>
43
44 namespace WTR {
45
46 static String coreAttributeToAtkAttribute(JSStringRef attribute)
47 {
48     size_t bufferSize = JSStringGetMaximumUTF8CStringSize(attribute);
49     GOwnPtr<gchar> buffer(static_cast<gchar*>(g_malloc(bufferSize)));
50     JSStringGetUTF8CString(attribute, buffer.get(), bufferSize);
51
52     String attributeString = String::fromUTF8(buffer.get());
53     return attributeString == "AXPlaceholderValue" ? "placeholder-text" : String();
54 }
55
56 static void attributesClear(AtkAttributeSet* attributesSet)
57 {
58     for (GSList* attributes = attributesSet; attributes; attributes = attributes->next) {
59         AtkAttribute* atkAttribute = static_cast<AtkAttribute*>(attributes->data);
60         g_free(atkAttribute->name);
61         g_free(atkAttribute->value);
62         g_free(atkAttribute);
63     }
64 }
65
66 static gchar* attributeSetToString(AtkAttributeSet* attributeSet)
67 {
68     GOwnPtr<GSList> atkAttributes(attributeSet);
69     GString* str = g_string_new(0);
70     for (GSList* attributes = atkAttributes.get(); attributes; attributes = attributes->next) {
71         AtkAttribute* attribute = static_cast<AtkAttribute*>(attributes->data);
72         GOwnPtr<gchar> attributeData(g_strconcat(attribute->name, ":", attribute->value, NULL));
73         g_string_append(str, attributeData.get());
74         if (attributes->next)
75             g_string_append(str, ", ");
76     }
77
78     attributesClear(atkAttributes.get());
79
80     return g_string_free(str, FALSE);
81 }
82
83 static bool checkElementState(PlatformUIElement element, AtkStateType stateType)
84 {
85     if (!ATK_IS_OBJECT(element.get()))
86         return false;
87
88     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(element.get())));
89     return atk_state_set_contains_state(stateSet.get(), stateType);
90 }
91
92 static JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange)
93 {
94     GOwnPtr<gchar> rangeString(g_strdup("{0, 0}"));
95
96     if (!element || !ATK_IS_OBJECT(element.get()))
97         return JSStringCreateWithUTF8CString(rangeString.get());
98
99     AtkObject* axTable = atk_object_get_parent(ATK_OBJECT(element.get()));
100     if (!axTable || !ATK_IS_TABLE(axTable))
101         return JSStringCreateWithUTF8CString(rangeString.get());
102
103     // Look for the cell in the table.
104     gint indexInParent = atk_object_get_index_in_parent(ATK_OBJECT(element.get()));
105     if (indexInParent == -1)
106         return JSStringCreateWithUTF8CString(rangeString.get());
107
108     int row = -1;
109     int column = -1;
110     row = atk_table_get_row_at_index(ATK_TABLE(axTable), indexInParent);
111     column = atk_table_get_column_at_index(ATK_TABLE(axTable), indexInParent);
112
113     // Get the actual values, if row and columns are valid values.
114     if (row != -1 && column != -1) {
115         int base = 0;
116         int length = 0;
117         if (isRowRange) {
118             base = row;
119             length = atk_table_get_row_extent_at(ATK_TABLE(axTable), row, column);
120         } else {
121             base = column;
122             length = atk_table_get_column_extent_at(ATK_TABLE(axTable), row, column);
123         }
124         rangeString.set(g_strdup_printf("{%d, %d}", base, length));
125     }
126
127     return JSStringCreateWithUTF8CString(rangeString.get());
128 }
129
130 static void alterCurrentValue(PlatformUIElement element, int factor)
131 {
132     if (!element || !ATK_IS_VALUE(element.get()))
133         return;
134
135     GValue currentValue = G_VALUE_INIT;
136     atk_value_get_current_value(ATK_VALUE(element.get()), &currentValue);
137
138     GValue increment = G_VALUE_INIT;
139     atk_value_get_minimum_increment(ATK_VALUE(element.get()), &increment);
140
141     GValue newValue = G_VALUE_INIT;
142     g_value_init(&newValue, G_TYPE_DOUBLE);
143
144     g_value_set_float(&newValue, g_value_get_float(&currentValue) + factor * g_value_get_float(&increment));
145     atk_value_set_current_value(ATK_VALUE(element.get()), &newValue);
146
147     g_value_unset(&newValue);
148     g_value_unset(&increment);
149     g_value_unset(&currentValue);
150 }
151
152 static gchar* replaceCharactersForResults(gchar* str)
153 {
154     WTF::String uString = WTF::String::fromUTF8(str);
155
156     // The object replacement character is passed along to ATs so we need to be
157     // able to test for their presence and do so without causing test failures.
158     uString.replace(objectReplacementCharacter, "<obj>");
159
160     // The presence of newline characters in accessible text of a single object
161     // is appropriate, but it makes test results (especially the accessible tree)
162     // harder to read.
163     uString.replace("\n", "<\\n>");
164
165     return g_strdup(uString.utf8().data());
166 }
167
168 static const gchar* roleToString(AtkRole role)
169 {
170     switch (role) {
171     case ATK_ROLE_ALERT:
172         return "AXRole: AXAlert";
173     case ATK_ROLE_CANVAS:
174         return "AXRole: AXCanvas";
175     case ATK_ROLE_CHECK_BOX:
176         return "AXRole: AXCheckBox";
177     case ATK_ROLE_COLUMN_HEADER:
178         return "AXRole: AXColumnHeader";
179     case ATK_ROLE_COMBO_BOX:
180         return "AXRole: AXComboBox";
181     case ATK_ROLE_DOCUMENT_FRAME:
182         return "AXRole: AXWebArea";
183     case ATK_ROLE_ENTRY:
184         return "AXRole: AXTextField";
185     case ATK_ROLE_FOOTER:
186         return "AXRole: AXFooter";
187     case ATK_ROLE_FORM:
188         return "AXRole: AXForm";
189     case ATK_ROLE_GROUPING:
190         return "AXRole: AXGroup";
191     case ATK_ROLE_HEADING:
192         return "AXRole: AXHeading";
193     case ATK_ROLE_IMAGE:
194         return "AXRole: AXImage";
195     case ATK_ROLE_IMAGE_MAP:
196         return "AXRole: AXImageMap";
197     case ATK_ROLE_LABEL:
198         return "AXRole: AXLabel";
199     case ATK_ROLE_LINK:
200         return "AXRole: AXLink";
201     case ATK_ROLE_LIST:
202         return "AXRole: AXList";
203     case ATK_ROLE_LIST_BOX:
204         return "AXRole: AXListBox";
205     case ATK_ROLE_LIST_ITEM:
206         return "AXRole: AXListItem";
207     case ATK_ROLE_MENU:
208         return "AXRole: AXMenu";
209     case ATK_ROLE_MENU_BAR:
210         return "AXRole: AXMenuBar";
211     case ATK_ROLE_MENU_ITEM:
212         return "AXRole: AXMenuItem";
213     case ATK_ROLE_PAGE_TAB:
214         return "AXRole: AXTab";
215     case ATK_ROLE_PAGE_TAB_LIST:
216         return "AXRole: AXTabGroup";
217     case ATK_ROLE_PANEL:
218         return "AXRole: AXGroup";
219     case ATK_ROLE_PARAGRAPH:
220         return "AXRole: AXParagraph";
221     case ATK_ROLE_PASSWORD_TEXT:
222         return "AXRole: AXPasswordField";
223     case ATK_ROLE_PUSH_BUTTON:
224         return "AXRole: AXButton";
225     case ATK_ROLE_RADIO_BUTTON:
226         return "AXRole: AXRadioButton";
227     case ATK_ROLE_ROW_HEADER:
228         return "AXRole: AXRowHeader";
229     case ATK_ROLE_RULER:
230         return "AXRole: AXRuler";
231     case ATK_ROLE_SCROLL_BAR:
232         return "AXRole: AXScrollBar";
233     case ATK_ROLE_SCROLL_PANE:
234         return "AXRole: AXScrollArea";
235     case ATK_ROLE_SECTION:
236         return "AXRole: AXDiv";
237     case ATK_ROLE_SEPARATOR:
238         return "AXRole: AXHorizontalRule";
239     case ATK_ROLE_SLIDER:
240         return "AXRole: AXSlider";
241     case ATK_ROLE_SPIN_BUTTON:
242         return "AXRole: AXSpinButton";
243     case ATK_ROLE_TABLE:
244         return "AXRole: AXTable";
245     case ATK_ROLE_TABLE_CELL:
246         return "AXRole: AXCell";
247     case ATK_ROLE_TABLE_COLUMN_HEADER:
248         return "AXRole: AXColumnHeader";
249     case ATK_ROLE_TABLE_ROW:
250         return "AXRole: AXRow";
251     case ATK_ROLE_TABLE_ROW_HEADER:
252         return "AXRole: AXRowHeader";
253     case ATK_ROLE_TOGGLE_BUTTON:
254         return "AXRole: AXToggleButton";
255     case ATK_ROLE_TOOL_BAR:
256         return "AXRole: AXToolbar";
257     case ATK_ROLE_TOOL_TIP:
258         return "AXRole: AXUserInterfaceTooltip";
259     case ATK_ROLE_TREE:
260         return "AXRole: AXTree";
261     case ATK_ROLE_TREE_TABLE:
262         return "AXRole: AXTreeGrid";
263     case ATK_ROLE_TREE_ITEM:
264         return "AXRole: AXTreeItem";
265     case ATK_ROLE_WINDOW:
266         return "AXRole: AXWindow";
267     case ATK_ROLE_UNKNOWN:
268         return "AXRole: AXUnknown";
269     default:
270         // We want to distinguish ATK_ROLE_UNKNOWN from a known AtkRole which
271         // our DRT isn't properly handling.
272         return "AXRole: FIXME not identified";
273     }
274 }
275
276 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
277     : m_element(element)
278 {
279 }
280
281 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
282     : JSWrappable()
283     , m_element(other.m_element)
284 {
285 }
286
287 AccessibilityUIElement::~AccessibilityUIElement()
288 {
289 }
290
291 bool AccessibilityUIElement::isEqual(AccessibilityUIElement* otherElement)
292 {
293     return m_element == otherElement->platformUIElement();
294 }
295
296 void AccessibilityUIElement::getChildren(Vector<RefPtr<AccessibilityUIElement> >& children)
297 {
298     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
299         return;
300
301     int count = childrenCount();
302     for (int i = 0; i < count; i++) {
303         GRefPtr<AtkObject> child = adoptGRef(atk_object_ref_accessible_child(ATK_OBJECT(m_element.get()), i));
304         children.append(AccessibilityUIElement::create(child.get()));
305     }
306 }
307
308 void AccessibilityUIElement::getChildrenWithRange(Vector<RefPtr<AccessibilityUIElement> >& children, unsigned location, unsigned length)
309 {
310     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
311         return;
312     unsigned end = location + length;
313     for (unsigned i = location; i < end; i++) {
314         GRefPtr<AtkObject> child = adoptGRef(atk_object_ref_accessible_child(ATK_OBJECT(m_element.get()), i));
315         children.append(AccessibilityUIElement::create(child.get()));
316     }
317 }
318
319 int AccessibilityUIElement::childrenCount()
320 {
321     if (!m_element)
322         return 0;
323
324     return atk_object_get_n_accessible_children(ATK_OBJECT(m_element.get()));
325 }
326
327 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::elementAtPoint(int x, int y)
328 {
329     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
330         return 0;
331
332     GRefPtr<AtkObject> objectAtPoint = adoptGRef(atk_component_ref_accessible_at_point(ATK_COMPONENT(m_element.get()), x, y, ATK_XY_WINDOW));
333     return objectAtPoint ? AccessibilityUIElement::create(objectAtPoint.get()) : 0;
334 }
335
336 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
337 {
338     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
339         return 0;
340
341     Vector<RefPtr<AccessibilityUIElement> > children;
342     getChildren(children);
343
344     unsigned count = children.size();
345     for (unsigned i = 0; i < count; i++)
346         if (children[i]->isEqual(element))
347             return i;
348
349     return 0;
350 }
351
352 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::childAtIndex(unsigned index)
353 {
354     Vector<RefPtr<AccessibilityUIElement> > children;
355     getChildrenWithRange(children, index, 1);
356
357     if (children.size() == 1)
358         return children[0];
359
360     return 0;
361 }
362
363 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
364 {
365     // FIXME: implement
366     return 0;
367 }
368
369 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
370 {
371     // FIXME: implement
372     return 0;
373 }
374
375 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
376 {
377     // FIXME: implement
378     return 0;
379 }
380
381 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
382 {
383     // FIXME: implement
384     return 0;
385 }
386
387 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::rowAtIndex(unsigned index)
388 {
389     // FIXME: implement
390     return 0;
391 }
392
393 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedChildAtIndex(unsigned index) const
394 {
395     // FIXME: implement
396     return 0;
397 }
398
399 unsigned AccessibilityUIElement::selectedChildrenCount() const
400 {
401     // FIXME: implement
402     return 0;
403 }
404
405 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::selectedRowAtIndex(unsigned index)
406 {
407     // FIXME: implement
408     return 0;
409 }
410
411 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::titleUIElement()
412 {
413     if (!m_element)
414         return 0;
415
416     AtkRelationSet* set = atk_object_ref_relation_set(ATK_OBJECT(m_element.get()));
417     if (!set)
418         return 0;
419
420     AtkObject* target = 0;
421     int count = atk_relation_set_get_n_relations(set);
422     for (int i = 0; i < count; i++) {
423         AtkRelation* relation = atk_relation_set_get_relation(set, i);
424         if (atk_relation_get_relation_type(relation) == ATK_RELATION_LABELLED_BY) {
425             GPtrArray* targetList = atk_relation_get_target(relation);
426             if (targetList->len)
427                 target = static_cast<AtkObject*>(g_ptr_array_index(targetList, 0));
428         }
429     }
430
431     g_object_unref(set);
432     return target ? AccessibilityUIElement::create(target) : 0;
433 }
434
435 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::parentElement()
436 {
437     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
438         return 0;
439
440     AtkObject* parent = atk_object_get_parent(ATK_OBJECT(m_element.get()));
441     return parent ? AccessibilityUIElement::create(parent) : 0;
442 }
443
444 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::disclosedByRow()
445 {
446     // FIXME: implement
447     return 0;
448 }
449
450 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfLinkedUIElements()
451 {
452     // FIXME: implement
453     return JSStringCreateWithCharacters(0, 0);
454 }
455
456 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfDocumentLinks()
457 {
458     // FIXME: implement
459     return JSStringCreateWithCharacters(0, 0);
460 }
461
462 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfChildren()
463 {
464     // FIXME: implement
465     return JSStringCreateWithCharacters(0, 0);
466 }
467
468 JSRetainPtr<JSStringRef> AccessibilityUIElement::allAttributes()
469 {
470     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
471         return JSStringCreateWithCharacters(0, 0);
472
473     GOwnPtr<gchar> attributeData(attributeSetToString(atk_object_get_attributes(ATK_OBJECT(m_element.get()))));
474     return JSStringCreateWithUTF8CString(attributeData.get());
475 }
476
477 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
478 {
479     if (!m_element)
480         return JSStringCreateWithCharacters(0, 0);
481
482     String atkAttributeName = coreAttributeToAtkAttribute(attribute);
483     if (atkAttributeName.isNull())
484         return JSStringCreateWithCharacters(0, 0);
485
486     GOwnPtr<gchar> attributeValue;
487     GOwnPtr<GSList> objectAttributes(atk_object_get_attributes(ATK_OBJECT(m_element.get())));
488     for (GSList* attributes =  objectAttributes.get(); attributes; attributes = attributes->next) {
489         AtkAttribute* atkAttribute = static_cast<AtkAttribute*>(attributes->data);
490         if (!strcmp(atkAttribute->name, atkAttributeName.utf8().data())) {
491             attributeValue.set(g_strdup(atkAttribute->value));
492             break;
493         }
494     }
495
496     attributesClear(objectAttributes.get());
497
498     return JSStringCreateWithUTF8CString(attributeValue.get());
499 }
500
501 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
502 {
503     // FIXME: implement
504     return 0.0f;
505 }
506
507 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementAttributeValue(JSStringRef attribute) const
508 {
509     // FIXME: implement
510     return 0;
511 }
512
513 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
514 {
515     // FIXME: implement
516     return false;
517 }
518
519 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
520 {
521     // FIXME: implement
522     return false;
523 }
524
525 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
526 {
527     // FIXME: implement
528     return false;
529 }
530
531 JSRetainPtr<JSStringRef> AccessibilityUIElement::parameterizedAttributeNames()
532 {
533     // FIXME: implement
534     return JSStringCreateWithCharacters(0, 0);
535 }
536
537 JSRetainPtr<JSStringRef> AccessibilityUIElement::role()
538 {
539     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
540         return JSStringCreateWithCharacters(0, 0);
541
542     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get()));
543     if (!role)
544         return JSStringCreateWithCharacters(0, 0);
545
546     GOwnPtr<gchar> axRole(g_strdup(roleToString(role)));
547     return JSStringCreateWithUTF8CString(axRole.get());
548 }
549
550 JSRetainPtr<JSStringRef> AccessibilityUIElement::subrole()
551 {
552     // FIXME: implement
553     return JSStringCreateWithCharacters(0, 0);
554 }
555
556 JSRetainPtr<JSStringRef> AccessibilityUIElement::roleDescription()
557 {
558     // FIXME: implement
559     return JSStringCreateWithCharacters(0, 0);
560 }
561
562 JSRetainPtr<JSStringRef> AccessibilityUIElement::title()
563 {
564     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
565         return JSStringCreateWithCharacters(0, 0);
566
567     const gchar* name = atk_object_get_name(ATK_OBJECT(m_element.get()));
568     GOwnPtr<gchar> axTitle(g_strdup_printf("AXTitle: %s", name ? name : ""));
569
570     return JSStringCreateWithUTF8CString(axTitle.get());
571 }
572
573 JSRetainPtr<JSStringRef> AccessibilityUIElement::description()
574 {
575     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
576         return JSStringCreateWithCharacters(0, 0);
577
578     const gchar* description = atk_object_get_description(ATK_OBJECT(m_element.get()));
579     if (!description)
580         return JSStringCreateWithCharacters(0, 0);
581
582     GOwnPtr<gchar> axDesc(g_strdup_printf("AXDescription: %s", description));
583
584     return JSStringCreateWithUTF8CString(axDesc.get());
585 }
586
587 JSRetainPtr<JSStringRef> AccessibilityUIElement::orientation() const
588 {
589     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
590         return JSStringCreateWithCharacters(0, 0);
591
592     const gchar* axOrientation = 0;
593     if (checkElementState(m_element.get(), ATK_STATE_HORIZONTAL))
594         axOrientation = "AXOrientation: AXHorizontalOrientation";
595     else if (checkElementState(m_element.get(), ATK_STATE_VERTICAL))
596         axOrientation = "AXOrientation: AXVerticalOrientation";
597
598     if (!axOrientation)
599         return JSStringCreateWithCharacters(0, 0);
600
601     return JSStringCreateWithUTF8CString(axOrientation);
602 }
603
604 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringValue()
605 {
606     if (!m_element || !ATK_IS_TEXT(m_element.get()))
607         return JSStringCreateWithCharacters(0, 0);
608
609     GOwnPtr<gchar> text(atk_text_get_text(ATK_TEXT(m_element.get()), 0, -1));
610     GOwnPtr<gchar> textWithReplacedCharacters(replaceCharactersForResults(text.get()));
611     GOwnPtr<gchar> axValue(g_strdup_printf("AXValue: %s", textWithReplacedCharacters.get()));
612
613     return JSStringCreateWithUTF8CString(axValue.get());
614 }
615
616 JSRetainPtr<JSStringRef> AccessibilityUIElement::language()
617 {
618     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
619         return JSStringCreateWithCharacters(0, 0);
620
621     const gchar* locale = atk_object_get_object_locale(ATK_OBJECT(m_element.get()));
622     if (!locale)
623         return JSStringCreateWithCharacters(0, 0);
624
625     return JSStringCreateWithUTF8CString(g_strdup_printf("AXLanguage: %s", locale));
626 }
627
628 JSRetainPtr<JSStringRef> AccessibilityUIElement::helpText() const
629 {
630     // FIXME: implement
631     // We need a way to call WebCore::AccessibilityObject::helpText()
632     // from here, probably a new helper class in WebProcess/WebCoreSupport.
633     return JSStringCreateWithCharacters(0, 0);
634 }
635
636 double AccessibilityUIElement::x()
637 {
638     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
639         return 0.0f;
640
641     int x, y;
642     atk_component_get_position(ATK_COMPONENT(m_element.get()), &x, &y, ATK_XY_SCREEN);
643     return x;
644 }
645
646 double AccessibilityUIElement::y()
647 {
648     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
649         return 0.0f;
650
651     int x, y;
652     atk_component_get_position(ATK_COMPONENT(m_element.get()), &x, &y, ATK_XY_SCREEN);
653     return y;
654 }
655
656 double AccessibilityUIElement::width()
657 {
658     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
659         return 0.0f;
660
661     int width, height;
662     atk_component_get_size(ATK_COMPONENT(m_element.get()), &width, &height);
663     return width;
664 }
665
666 double AccessibilityUIElement::height()
667 {
668     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
669         return 0.0f;
670
671     int width, height;
672     atk_component_get_size(ATK_COMPONENT(m_element.get()), &width, &height);
673     return height;
674 }
675
676 double AccessibilityUIElement::clickPointX()
677 {
678     // FIXME: implement
679     return 0.0f;
680 }
681
682 double AccessibilityUIElement::clickPointY()
683 {
684     // FIXME: implement
685     return 0.0f;
686 }
687
688 double AccessibilityUIElement::intValue() const
689 {
690     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
691         return 0.0f;
692
693     GValue value = G_VALUE_INIT;
694     atk_value_get_current_value(ATK_VALUE(m_element.get()), &value);
695     if (!G_VALUE_HOLDS_FLOAT(&value))
696         return 0.0f;
697
698     return g_value_get_float(&value);
699 }
700
701 double AccessibilityUIElement::minValue()
702 {
703     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
704         return 0.0f;
705
706     GValue value = G_VALUE_INIT;
707     atk_value_get_minimum_value(ATK_VALUE(m_element.get()), &value);
708     if (!G_VALUE_HOLDS_FLOAT(&value))
709         return 0.0f;
710
711     return g_value_get_float(&value);
712 }
713
714 double AccessibilityUIElement::maxValue()
715 {
716     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
717         return 0.0f;
718
719     GValue value = G_VALUE_INIT;
720     atk_value_get_maximum_value(ATK_VALUE(m_element.get()), &value);
721     if (!G_VALUE_HOLDS_FLOAT(&value))
722         return 0.0f;
723
724     return g_value_get_float(&value);
725 }
726
727 JSRetainPtr<JSStringRef> AccessibilityUIElement::valueDescription()
728 {
729     // FIXME: implement
730     return JSStringCreateWithCharacters(0, 0);
731 }
732
733 int AccessibilityUIElement::insertionPointLineNumber()
734 {
735     // FIXME: implement
736     return -1;
737 }
738
739 bool AccessibilityUIElement::isPressActionSupported()
740 {
741     // FIXME: implement
742     return false;
743 }
744
745 bool AccessibilityUIElement::isIncrementActionSupported()
746 {
747     // FIXME: implement
748     return false;
749 }
750
751 bool AccessibilityUIElement::isDecrementActionSupported()
752 {
753     // FIXME: implement
754     return false;
755 }
756
757 bool AccessibilityUIElement::isEnabled()
758 {
759     return checkElementState(m_element.get(), ATK_STATE_ENABLED);
760 }
761
762 bool AccessibilityUIElement::isRequired() const
763 {
764     // FIXME: implement
765     return false;
766 }
767
768 bool AccessibilityUIElement::isFocused() const
769 {
770     return checkElementState(m_element.get(), ATK_STATE_FOCUSED);
771 }
772
773 bool AccessibilityUIElement::isSelected() const
774 {
775     return checkElementState(m_element.get(), ATK_STATE_SELECTED);
776 }
777
778 bool AccessibilityUIElement::isExpanded() const
779 {
780     return checkElementState(m_element.get(), ATK_STATE_EXPANDED);
781 }
782
783 bool AccessibilityUIElement::isChecked() const
784 {
785     return checkElementState(m_element.get(), ATK_STATE_CHECKED);
786 }
787
788 int AccessibilityUIElement::hierarchicalLevel() const
789 {
790     // FIXME: implement
791     return 0;
792 }
793
794 JSRetainPtr<JSStringRef> AccessibilityUIElement::speak()
795 {
796     // FIXME: implement
797     return JSStringCreateWithCharacters(0, 0);
798 }
799
800 bool AccessibilityUIElement::ariaIsGrabbed() const
801 {
802     // FIXME: implement
803     return false;
804 }
805
806 JSRetainPtr<JSStringRef> AccessibilityUIElement::ariaDropEffects() const
807 {
808     // FIXME: implement
809     return JSStringCreateWithCharacters(0, 0);
810 }
811
812 // parameterized attributes
813 int AccessibilityUIElement::lineForIndex(int index)
814 {
815     // FIXME: implement
816     return 0;
817 }
818
819 JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForLine(int line)
820 {
821     // FIXME: implement
822     return JSStringCreateWithCharacters(0, 0);
823 }
824
825 JSRetainPtr<JSStringRef> AccessibilityUIElement::rangeForPosition(int x, int y)
826 {
827     // FIXME: implement
828     return JSStringCreateWithCharacters(0, 0);
829 }
830
831 JSRetainPtr<JSStringRef> AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
832 {
833     // FIXME: implement
834     return JSStringCreateWithCharacters(0, 0);
835 }
836
837 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
838 {
839     // FIXME: implement
840     return JSStringCreateWithCharacters(0, 0);
841 }
842
843 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForRange(unsigned location, unsigned length)
844 {
845     // FIXME: implement
846     return JSStringCreateWithCharacters(0, 0);
847 }
848
849 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
850 {
851     // FIXME: implement
852     return false;
853 }
854
855 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly)
856 {
857     // FIXME: implement
858     return 0;
859 }
860
861 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumnHeaders()
862 {
863     // FIXME: implement
864     return JSStringCreateWithCharacters(0, 0);
865 }
866
867 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfRowHeaders()
868 {
869     // FIXME: implement
870     return JSStringCreateWithCharacters(0, 0);
871 }
872
873 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumns()
874 {
875     // FIXME: implement
876     return JSStringCreateWithCharacters(0, 0);
877 }
878
879 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfRows()
880 {
881     // FIXME: implement
882     return JSStringCreateWithCharacters(0, 0);
883 }
884
885 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfVisibleCells()
886 {
887     // FIXME: implement
888     return JSStringCreateWithCharacters(0, 0);
889 }
890
891 JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfHeader()
892 {
893     // FIXME: implement
894     return JSStringCreateWithCharacters(0, 0);
895 }
896
897 int AccessibilityUIElement::rowCount()
898 {
899     if (!m_element || !ATK_IS_TABLE(m_element.get()))
900         return 0;
901
902     return atk_table_get_n_rows(ATK_TABLE(m_element.get()));
903 }
904
905 int AccessibilityUIElement::columnCount()
906 {
907     if (!m_element || !ATK_IS_TABLE(m_element.get()))
908         return 0;
909
910     return atk_table_get_n_columns(ATK_TABLE(m_element.get()));
911 }
912
913 int AccessibilityUIElement::indexInTable()
914 {
915     // FIXME: implement
916     return -1;
917 }
918
919 JSRetainPtr<JSStringRef> AccessibilityUIElement::rowIndexRange()
920 {
921     // Range in table for rows.
922     return indexRangeInTable(m_element.get(), true);
923 }
924
925 JSRetainPtr<JSStringRef> AccessibilityUIElement::columnIndexRange()
926 {
927     // Range in table for columns.
928     return indexRangeInTable(m_element.get(), false);
929 }
930
931 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row)
932 {
933     if (!m_element || !ATK_IS_TABLE(m_element.get()))
934         return 0;
935
936     // Adopt the AtkObject representing the cell because
937     // at_table_ref_at() transfers full ownership.
938     GRefPtr<AtkObject> foundCell = adoptGRef(atk_table_ref_at(ATK_TABLE(m_element.get()), row, col));
939     return foundCell ? AccessibilityUIElement::create(foundCell.get()) : 0;
940 }
941
942 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::horizontalScrollbar() const
943 {
944     // FIXME: implement
945     return 0;
946 }
947
948 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::verticalScrollbar() const
949 {
950     // FIXME: implement
951     return 0;
952 }
953
954 JSRetainPtr<JSStringRef> AccessibilityUIElement::selectedTextRange()
955 {
956     // FIXME: implement
957     return JSStringCreateWithCharacters(0, 0);
958 }
959
960 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
961 {
962     // FIXME: implement
963 }
964
965 void AccessibilityUIElement::increment()
966 {
967     alterCurrentValue(m_element.get(), 1);
968 }
969
970 void AccessibilityUIElement::decrement()
971 {
972     alterCurrentValue(m_element.get(), -1);
973 }
974
975 void AccessibilityUIElement::showMenu()
976 {
977     // FIXME: implement
978 }
979
980 void AccessibilityUIElement::press()
981 {
982     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
983         return;
984
985     if (!ATK_IS_ACTION(m_element.get()))
986         return;
987
988     // Only one action per object is supported so far.
989     atk_action_do_action(ATK_ACTION(m_element.get()), 0);
990 }
991
992 void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement* element) const
993 {
994     // FIXME: implement
995 }
996
997 JSRetainPtr<JSStringRef> AccessibilityUIElement::accessibilityValue() const
998 {
999     // FIXME: implement
1000     return JSStringCreateWithCharacters(0, 0);
1001 }
1002
1003 JSRetainPtr<JSStringRef> AccessibilityUIElement::documentEncoding()
1004 {
1005     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
1006         return JSStringCreateWithCharacters(0, 0);
1007
1008     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get()));
1009     if (role != ATK_ROLE_DOCUMENT_FRAME)
1010         return JSStringCreateWithCharacters(0, 0);
1011
1012     return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element.get()), "Encoding"));
1013 }
1014
1015 JSRetainPtr<JSStringRef> AccessibilityUIElement::documentURI()
1016 {
1017     if (!m_element || !ATK_IS_OBJECT(m_element.get()))
1018         return JSStringCreateWithCharacters(0, 0);
1019
1020     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element.get()));
1021     if (role != ATK_ROLE_DOCUMENT_FRAME)
1022         return JSStringCreateWithCharacters(0, 0);
1023
1024     return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element.get()), "URI"));
1025 }
1026
1027 JSRetainPtr<JSStringRef> AccessibilityUIElement::url()
1028 {
1029     // FIXME: implement
1030     return JSStringCreateWithCharacters(0, 0);
1031 }
1032
1033 bool AccessibilityUIElement::addNotificationListener(JSValueRef functionCallback)
1034 {
1035     // FIXME: implement
1036     return true;
1037 }
1038
1039 bool AccessibilityUIElement::removeNotificationListener()
1040 {
1041     // FIXME: implement
1042     return true;
1043 }
1044
1045 bool AccessibilityUIElement::isFocusable() const
1046 {
1047     return checkElementState(m_element.get(), ATK_STATE_FOCUSABLE);
1048 }
1049
1050 bool AccessibilityUIElement::isSelectable() const
1051 {
1052     return checkElementState(m_element.get(), ATK_STATE_SELECTABLE);
1053 }
1054
1055 bool AccessibilityUIElement::isMultiSelectable() const
1056 {
1057     return checkElementState(m_element.get(), ATK_STATE_MULTISELECTABLE);
1058 }
1059
1060 bool AccessibilityUIElement::isVisible() const
1061 {
1062     return checkElementState(m_element.get(), ATK_STATE_VISIBLE);
1063 }
1064
1065 bool AccessibilityUIElement::isOffScreen() const
1066 {
1067     // FIXME: implement
1068     return false;
1069 }
1070
1071 bool AccessibilityUIElement::isCollapsed() const
1072 {
1073     // FIXME: implement
1074     return false;
1075 }
1076
1077 bool AccessibilityUIElement::isIgnored() const
1078 {
1079     // FIXME: implement
1080     return false;
1081 }
1082
1083 bool AccessibilityUIElement::hasPopup() const
1084 {
1085     // FIXME: implement
1086     return false;
1087 }
1088
1089 void AccessibilityUIElement::takeFocus()
1090 {
1091     // FIXME: implement
1092 }
1093
1094 void AccessibilityUIElement::takeSelection()
1095 {
1096     // FIXME: implement
1097 }
1098
1099 void AccessibilityUIElement::addSelection()
1100 {
1101     // FIXME: implement
1102 }
1103
1104 void AccessibilityUIElement::removeSelection()
1105 {
1106     // FIXME: implement
1107 }
1108
1109 // Text markers
1110 PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement* element)
1111 {
1112     // FIXME: implement
1113     return 0;
1114 }
1115
1116 int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange* range)
1117 {
1118     // FIXME: implement
1119     return 0;
1120 }
1121
1122 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::previousTextMarker(AccessibilityTextMarker* textMarker)
1123 {
1124     // FIXME: implement
1125     return 0;
1126 }
1127
1128 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::nextTextMarker(AccessibilityTextMarker* textMarker)
1129 {
1130     // FIXME: implement
1131     return 0;
1132 }
1133
1134 JSRetainPtr<JSStringRef> AccessibilityUIElement::stringForTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
1135 {
1136     // FIXME: implement
1137     return JSStringCreateWithCharacters(0, 0);
1138 }
1139
1140 PassRefPtr<AccessibilityTextMarkerRange> AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker)
1141 {
1142     // FIXME: implement
1143     return 0;
1144 }
1145
1146 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1147 {
1148     // FIXME: implement
1149     return 0;
1150 }
1151
1152 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1153 {
1154     // FIXME: implement
1155     return 0;
1156 }
1157
1158 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForPoint(int x, int y)
1159 {
1160     // FIXME: implement
1161     return 0;
1162 }
1163
1164 PassRefPtr<AccessibilityUIElement> AccessibilityUIElement::accessibilityElementForTextMarker(AccessibilityTextMarker* marker)
1165 {
1166     // FIXME: implement
1167     return 0;
1168 }
1169
1170 bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef attribute, AccessibilityTextMarkerRange* range)
1171 {
1172     // FIXME: implement
1173     return false;
1174 }
1175
1176 int AccessibilityUIElement::indexForTextMarker(AccessibilityTextMarker* marker)
1177 {
1178     // FIXME: implement
1179     return -1;
1180 }
1181
1182 bool AccessibilityUIElement::isTextMarkerValid(AccessibilityTextMarker* textMarker)
1183 {
1184     // FIXME: implement
1185     return false;
1186 }
1187
1188 PassRefPtr<AccessibilityTextMarker> AccessibilityUIElement::textMarkerForIndex(int textIndex)
1189 {
1190     // FIXME: implement
1191     return 0;
1192 }
1193
1194 void AccessibilityUIElement::scrollToMakeVisible()
1195 {
1196     // FIXME: implement
1197 }
1198
1199 JSRetainPtr<JSStringRef> AccessibilityUIElement::supportedActions() const
1200 {
1201     // FIXME: implement
1202     return 0;
1203 }
1204
1205 JSRetainPtr<JSStringRef> AccessibilityUIElement::pathDescription() const
1206 {
1207     notImplemented();
1208     return 0;
1209 }
1210
1211 JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPostscriptsDescription() const
1212 {
1213     notImplemented();
1214     return 0;
1215 }
1216
1217 JSRetainPtr<JSStringRef> AccessibilityUIElement::mathPrescriptsDescription() const
1218 {
1219     notImplemented();
1220     return 0;
1221 }
1222
1223 } // namespace WTR
1224
1225 #endif