• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Google 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "WebAXObjectProxy.h"
32 
33 #include "TestCommon.h"
34 #include "public/platform/WebCString.h"
35 #include "public/platform/WebPoint.h"
36 #include "public/platform/WebRect.h"
37 #include "public/platform/WebString.h"
38 
39 using namespace blink;
40 using namespace std;
41 
42 namespace WebTestRunner {
43 
44 namespace {
45 
46 // Map role value to string, matching Safari/Mac platform implementation to
47 // avoid rebaselining layout tests.
roleToString(WebAXRole role)48 string roleToString(WebAXRole role)
49 {
50     string result = "AXRole: AX";
51     switch (role) {
52     case WebAXRoleAlertDialog:
53         return result.append("AlertDialog");
54     case WebAXRoleAlert:
55         return result.append("Alert");
56     case WebAXRoleAnnotation:
57         return result.append("Annotation");
58     case WebAXRoleApplication:
59         return result.append("Application");
60     case WebAXRoleArticle:
61         return result.append("Article");
62     case WebAXRoleBanner:
63         return result.append("Banner");
64     case WebAXRoleBrowser:
65         return result.append("Browser");
66     case WebAXRoleBusyIndicator:
67         return result.append("BusyIndicator");
68     case WebAXRoleButton:
69         return result.append("Button");
70     case WebAXRoleCanvas:
71         return result.append("Canvas");
72     case WebAXRoleCell:
73         return result.append("Cell");
74     case WebAXRoleCheckBox:
75         return result.append("CheckBox");
76     case WebAXRoleColorWell:
77         return result.append("ColorWell");
78     case WebAXRoleColumnHeader:
79         return result.append("ColumnHeader");
80     case WebAXRoleColumn:
81         return result.append("Column");
82     case WebAXRoleComboBox:
83         return result.append("ComboBox");
84     case WebAXRoleComplementary:
85         return result.append("Complementary");
86     case WebAXRoleContentInfo:
87         return result.append("ContentInfo");
88     case WebAXRoleDefinition:
89         return result.append("Definition");
90     case WebAXRoleDescriptionListDetail:
91         return result.append("DescriptionListDetail");
92     case WebAXRoleDescriptionListTerm:
93         return result.append("DescriptionListTerm");
94     case WebAXRoleDialog:
95         return result.append("Dialog");
96     case WebAXRoleDirectory:
97         return result.append("Directory");
98     case WebAXRoleDisclosureTriangle:
99         return result.append("DisclosureTriangle");
100     case WebAXRoleDiv:
101         return result.append("Div");
102     case WebAXRoleDocument:
103         return result.append("Document");
104     case WebAXRoleDrawer:
105         return result.append("Drawer");
106     case WebAXRoleEditableText:
107         return result.append("EditableText");
108     case WebAXRoleFooter:
109         return result.append("Footer");
110     case WebAXRoleForm:
111         return result.append("Form");
112     case WebAXRoleGrid:
113         return result.append("Grid");
114     case WebAXRoleGroup:
115         return result.append("Group");
116     case WebAXRoleGrowArea:
117         return result.append("GrowArea");
118     case WebAXRoleHeading:
119         return result.append("Heading");
120     case WebAXRoleHelpTag:
121         return result.append("HelpTag");
122     case WebAXRoleHorizontalRule:
123         return result.append("HorizontalRule");
124     case WebAXRoleIgnored:
125         return result.append("Ignored");
126     case WebAXRoleImageMapLink:
127         return result.append("ImageMapLink");
128     case WebAXRoleImageMap:
129         return result.append("ImageMap");
130     case WebAXRoleImage:
131         return result.append("Image");
132     case WebAXRoleIncrementor:
133         return result.append("Incrementor");
134     case WebAXRoleInlineTextBox:
135         return result.append("InlineTextBox");
136     case WebAXRoleLabel:
137         return result.append("Label");
138     case WebAXRoleLegend:
139         return result.append("Legend");
140     case WebAXRoleLink:
141         return result.append("Link");
142     case WebAXRoleListBoxOption:
143         return result.append("ListBoxOption");
144     case WebAXRoleListBox:
145         return result.append("ListBox");
146     case WebAXRoleListItem:
147         return result.append("ListItem");
148     case WebAXRoleListMarker:
149         return result.append("ListMarker");
150     case WebAXRoleList:
151         return result.append("List");
152     case WebAXRoleLog:
153         return result.append("Log");
154     case WebAXRoleMain:
155         return result.append("Main");
156     case WebAXRoleMarquee:
157         return result.append("Marquee");
158     case WebAXRoleMathElement:
159         return result.append("MathElement");
160     case WebAXRoleMath:
161         return result.append("Math");
162     case WebAXRoleMatte:
163         return result.append("Matte");
164     case WebAXRoleMenuBar:
165         return result.append("MenuBar");
166     case WebAXRoleMenuButton:
167         return result.append("MenuButton");
168     case WebAXRoleMenuItem:
169         return result.append("MenuItem");
170     case WebAXRoleMenuListOption:
171         return result.append("MenuListOption");
172     case WebAXRoleMenuListPopup:
173         return result.append("MenuListPopup");
174     case WebAXRoleMenu:
175         return result.append("Menu");
176     case WebAXRoleNavigation:
177         return result.append("Navigation");
178     case WebAXRoleNote:
179         return result.append("Note");
180     case WebAXRoleOutline:
181         return result.append("Outline");
182     case WebAXRoleParagraph:
183         return result.append("Paragraph");
184     case WebAXRolePopUpButton:
185         return result.append("PopUpButton");
186     case WebAXRolePresentational:
187         return result.append("Presentational");
188     case WebAXRoleProgressIndicator:
189         return result.append("ProgressIndicator");
190     case WebAXRoleRadioButton:
191         return result.append("RadioButton");
192     case WebAXRoleRadioGroup:
193         return result.append("RadioGroup");
194     case WebAXRoleRegion:
195         return result.append("Region");
196     case WebAXRoleRootWebArea:
197         return result.append("RootWebArea");
198     case WebAXRoleRowHeader:
199         return result.append("RowHeader");
200     case WebAXRoleRow:
201         return result.append("Row");
202     case WebAXRoleRulerMarker:
203         return result.append("RulerMarker");
204     case WebAXRoleRuler:
205         return result.append("Ruler");
206     case WebAXRoleSVGRoot:
207         return result.append("SVGRoot");
208     case WebAXRoleScrollArea:
209         return result.append("ScrollArea");
210     case WebAXRoleScrollBar:
211         return result.append("ScrollBar");
212     case WebAXRoleSeamlessWebArea:
213         return result.append("SeamlessWebArea");
214     case WebAXRoleSearch:
215         return result.append("Search");
216     case WebAXRoleSheet:
217         return result.append("Sheet");
218     case WebAXRoleSlider:
219         return result.append("Slider");
220     case WebAXRoleSliderThumb:
221         return result.append("SliderThumb");
222     case WebAXRoleSpinButtonPart:
223         return result.append("SpinButtonPart");
224     case WebAXRoleSpinButton:
225         return result.append("SpinButton");
226     case WebAXRoleSplitGroup:
227         return result.append("SplitGroup");
228     case WebAXRoleSplitter:
229         return result.append("Splitter");
230     case WebAXRoleStaticText:
231         return result.append("StaticText");
232     case WebAXRoleStatus:
233         return result.append("Status");
234     case WebAXRoleSystemWide:
235         return result.append("SystemWide");
236     case WebAXRoleTabGroup:
237         return result.append("TabGroup");
238     case WebAXRoleTabList:
239         return result.append("TabList");
240     case WebAXRoleTabPanel:
241         return result.append("TabPanel");
242     case WebAXRoleTab:
243         return result.append("Tab");
244     case WebAXRoleTableHeaderContainer:
245         return result.append("TableHeaderContainer");
246     case WebAXRoleTable:
247         return result.append("Table");
248     case WebAXRoleTextArea:
249         return result.append("TextArea");
250     case WebAXRoleTextField:
251         return result.append("TextField");
252     case WebAXRoleTimer:
253         return result.append("Timer");
254     case WebAXRoleToggleButton:
255         return result.append("ToggleButton");
256     case WebAXRoleToolbar:
257         return result.append("Toolbar");
258     case WebAXRoleTreeGrid:
259         return result.append("TreeGrid");
260     case WebAXRoleTreeItem:
261         return result.append("TreeItem");
262     case WebAXRoleTree:
263         return result.append("Tree");
264     case WebAXRoleUnknown:
265         return result.append("Unknown");
266     case WebAXRoleUserInterfaceTooltip:
267         return result.append("UserInterfaceTooltip");
268     case WebAXRoleValueIndicator:
269         return result.append("ValueIndicator");
270     case WebAXRoleWebArea:
271         return result.append("WebArea");
272     case WebAXRoleWindow:
273         return result.append("Window");
274     default:
275         return result.append("Unknown");
276     }
277 }
278 
getDescription(const WebAXObject & object)279 string getDescription(const WebAXObject& object)
280 {
281     string description = object.accessibilityDescription().utf8();
282     return description.insert(0, "AXDescription: ");
283 }
284 
getHelpText(const WebAXObject & object)285 string getHelpText(const WebAXObject& object)
286 {
287     string helpText = object.helpText().utf8();
288     return helpText.insert(0, "AXHelp: ");
289 }
290 
getStringValue(const WebAXObject & object)291 string getStringValue(const WebAXObject& object)
292 {
293     string value;
294     if (object.role() == WebAXRoleColorWell) {
295         int r, g, b;
296         char buffer[100];
297         object.colorValue(r, g, b);
298         snprintf(buffer, sizeof(buffer), "rgb %7.5f %7.5f %7.5f 1", r / 255., g / 255., b / 255.);
299         value = buffer;
300     } else {
301         value = object.stringValue().utf8();
302     }
303     return value.insert(0, "AXValue: ");
304 }
305 
getRole(const WebAXObject & object)306 string getRole(const WebAXObject& object)
307 {
308     string roleString = roleToString(object.role());
309 
310     // Special-case canvas with fallback content because Chromium wants to
311     // treat this as essentially a separate role that it can map differently depending
312     // on the platform.
313     if (object.role() == WebAXRoleCanvas && object.canvasHasFallbackContent())
314         roleString += "WithFallbackContent";
315 
316     return roleString;
317 }
318 
getTitle(const WebAXObject & object)319 string getTitle(const WebAXObject& object)
320 {
321     string title = object.title().utf8();
322     return title.insert(0, "AXTitle: ");
323 }
324 
getOrientation(const WebAXObject & object)325 string getOrientation(const WebAXObject& object)
326 {
327     if (object.isVertical())
328         return "AXOrientation: AXVerticalOrientation";
329 
330     return "AXOrientation: AXHorizontalOrientation";
331 }
332 
getValueDescription(const WebAXObject & object)333 string getValueDescription(const WebAXObject& object)
334 {
335     string valueDescription = object.valueDescription().utf8();
336     return valueDescription.insert(0, "AXValueDescription: ");
337 }
338 
getAttributes(const WebAXObject & object)339 string getAttributes(const WebAXObject& object)
340 {
341     // FIXME: Concatenate all attributes of the AXObject.
342     string attributes(getTitle(object));
343     attributes.append("\n");
344     attributes.append(getRole(object));
345     attributes.append("\n");
346     attributes.append(getDescription(object));
347     return attributes;
348 }
349 
boundsForCharacter(const WebAXObject & object,int characterIndex)350 WebRect boundsForCharacter(const WebAXObject& object, int characterIndex)
351 {
352     BLINK_ASSERT(object.role() == WebAXRoleStaticText);
353     int end = 0;
354     for (unsigned i = 0; i < object.childCount(); i++) {
355         WebAXObject inlineTextBox = object.childAt(i);
356         BLINK_ASSERT(inlineTextBox.role() == WebAXRoleInlineTextBox);
357         int start = end;
358         end += inlineTextBox.stringValue().length();
359         if (end <= characterIndex)
360             continue;
361         WebRect inlineTextBoxRect = inlineTextBox.boundingBoxRect();
362         int localIndex = characterIndex - start;
363         WebVector<int> characterOffsets;
364         inlineTextBox.characterOffsets(characterOffsets);
365         BLINK_ASSERT(characterOffsets.size() > 0 && characterOffsets.size() == inlineTextBox.stringValue().length());
366         switch (inlineTextBox.textDirection()) {
367         case WebAXTextDirectionLR: {
368             if (localIndex) {
369                 int left = inlineTextBoxRect.x + characterOffsets[localIndex - 1];
370                 int width = characterOffsets[localIndex] - characterOffsets[localIndex - 1];
371                 return WebRect(left, inlineTextBoxRect.y, width, inlineTextBoxRect.height);
372             }
373             return WebRect(inlineTextBoxRect.x, inlineTextBoxRect.y, characterOffsets[0], inlineTextBoxRect.height);
374         }
375         case WebAXTextDirectionRL: {
376             int right = inlineTextBoxRect.x + inlineTextBoxRect.width;
377 
378             if (localIndex) {
379                 int left = right - characterOffsets[localIndex];
380                 int width = characterOffsets[localIndex] - characterOffsets[localIndex - 1];
381                 return WebRect(left, inlineTextBoxRect.y, width, inlineTextBoxRect.height);
382             }
383             int left = right - characterOffsets[0];
384             return WebRect(left, inlineTextBoxRect.y, characterOffsets[0], inlineTextBoxRect.height);
385         }
386         case WebAXTextDirectionTB: {
387             if (localIndex) {
388                 int top = inlineTextBoxRect.y + characterOffsets[localIndex - 1];
389                 int height = characterOffsets[localIndex] - characterOffsets[localIndex - 1];
390                 return WebRect(inlineTextBoxRect.x, top, inlineTextBoxRect.width, height);
391             }
392             return WebRect(inlineTextBoxRect.x, inlineTextBoxRect.y, inlineTextBoxRect.width, characterOffsets[0]);
393         }
394         case WebAXTextDirectionBT: {
395             int bottom = inlineTextBoxRect.y + inlineTextBoxRect.height;
396 
397             if (localIndex) {
398                 int top = bottom - characterOffsets[localIndex];
399                 int height = characterOffsets[localIndex] - characterOffsets[localIndex - 1];
400                 return WebRect(inlineTextBoxRect.x, top, inlineTextBoxRect.width, height);
401             }
402             int top = bottom - characterOffsets[0];
403             return WebRect(inlineTextBoxRect.x, top, inlineTextBoxRect.width, characterOffsets[0]);
404         }
405         }
406     }
407 
408     BLINK_ASSERT(false);
409     return WebRect();
410 }
411 
getBoundariesForOneWord(const WebAXObject & object,int characterIndex,int & wordStart,int & wordEnd)412 void getBoundariesForOneWord(const WebAXObject& object, int characterIndex, int& wordStart, int& wordEnd)
413 {
414     int end = 0;
415     for (unsigned i = 0; i < object.childCount(); i++) {
416         WebAXObject inlineTextBox = object.childAt(i);
417         BLINK_ASSERT(inlineTextBox.role() == WebAXRoleInlineTextBox);
418         int start = end;
419         end += inlineTextBox.stringValue().length();
420         if (end <= characterIndex)
421             continue;
422         int localIndex = characterIndex - start;
423 
424         WebVector<int> starts;
425         WebVector<int> ends;
426         inlineTextBox.wordBoundaries(starts, ends);
427         size_t wordCount = starts.size();
428         BLINK_ASSERT(ends.size() == wordCount);
429 
430         // If there are no words, use the InlineTextBox boundaries.
431         if (!wordCount) {
432             wordStart = start;
433             wordEnd = end;
434             return;
435         }
436 
437         // Look for a character within any word other than the last.
438         for (size_t j = 0; j < wordCount - 1; j++) {
439             if (localIndex <= ends[j]) {
440                 wordStart = start + starts[j];
441                 wordEnd = start + ends[j];
442                 return;
443             }
444         }
445 
446         // Return the last word by default.
447         wordStart = start + starts[wordCount - 1];
448         wordEnd = start + ends[wordCount - 1];
449         return;
450     }
451 }
452 
453 // Collects attributes into a string, delimited by dashes. Used by all methods
454 // that output lists of attributes: attributesOfLinkedUIElementsCallback,
455 // AttributesOfChildrenCallback, etc.
456 class AttributesCollector {
457 public:
collectAttributes(const WebAXObject & object)458     void collectAttributes(const WebAXObject& object)
459     {
460         m_attributes.append("\n------------\n");
461         m_attributes.append(getAttributes(object));
462     }
463 
attributes() const464     string attributes() const { return m_attributes; }
465 
466 private:
467     string m_attributes;
468 };
469 
470 }
471 
WebAXObjectProxy(const WebAXObject & object,Factory * factory)472 WebAXObjectProxy::WebAXObjectProxy(const WebAXObject& object, Factory* factory)
473     : m_accessibilityObject(object)
474     , m_factory(factory)
475 {
476 
477     BLINK_ASSERT(factory);
478 
479     //
480     // Properties
481     //
482 
483     bindProperty("role", &WebAXObjectProxy::roleGetterCallback);
484     bindProperty("title", &WebAXObjectProxy::titleGetterCallback);
485     bindProperty("description", &WebAXObjectProxy::descriptionGetterCallback);
486     bindProperty("helpText", &WebAXObjectProxy::helpTextGetterCallback);
487     bindProperty("stringValue", &WebAXObjectProxy::stringValueGetterCallback);
488     bindProperty("x", &WebAXObjectProxy::xGetterCallback);
489     bindProperty("y", &WebAXObjectProxy::yGetterCallback);
490     bindProperty("width", &WebAXObjectProxy::widthGetterCallback);
491     bindProperty("height", &WebAXObjectProxy::heightGetterCallback);
492     bindProperty("intValue", &WebAXObjectProxy::intValueGetterCallback);
493     bindProperty("minValue", &WebAXObjectProxy::minValueGetterCallback);
494     bindProperty("maxValue", &WebAXObjectProxy::maxValueGetterCallback);
495     bindProperty("valueDescription", &WebAXObjectProxy::valueDescriptionGetterCallback);
496     bindProperty("childrenCount", &WebAXObjectProxy::childrenCountGetterCallback);
497     bindProperty("insertionPointLineNumber", &WebAXObjectProxy::insertionPointLineNumberGetterCallback);
498     bindProperty("selectedTextRange", &WebAXObjectProxy::selectedTextRangeGetterCallback);
499     bindProperty("isEnabled", &WebAXObjectProxy::isEnabledGetterCallback);
500     bindProperty("isRequired", &WebAXObjectProxy::isRequiredGetterCallback);
501     bindProperty("isFocused", &WebAXObjectProxy::isFocusedGetterCallback);
502     bindProperty("isFocusable", &WebAXObjectProxy::isFocusableGetterCallback);
503     bindProperty("isSelected", &WebAXObjectProxy::isSelectedGetterCallback);
504     bindProperty("isSelectable", &WebAXObjectProxy::isSelectableGetterCallback);
505     bindProperty("isMultiSelectable", &WebAXObjectProxy::isMultiSelectableGetterCallback);
506     bindProperty("isSelectedOptionActive", &WebAXObjectProxy::isSelectedOptionActiveGetterCallback);
507     bindProperty("isExpanded", &WebAXObjectProxy::isExpandedGetterCallback);
508     bindProperty("isChecked", &WebAXObjectProxy::isCheckedGetterCallback);
509     bindProperty("isVisible", &WebAXObjectProxy::isVisibleGetterCallback);
510     bindProperty("isOffScreen", &WebAXObjectProxy::isOffScreenGetterCallback);
511     bindProperty("isCollapsed", &WebAXObjectProxy::isCollapsedGetterCallback);
512     bindProperty("hasPopup", &WebAXObjectProxy::hasPopupGetterCallback);
513     bindProperty("isValid", &WebAXObjectProxy::isValidGetterCallback);
514     bindProperty("isReadOnly", &WebAXObjectProxy::isReadOnlyGetterCallback);
515     bindProperty("orientation", &WebAXObjectProxy::orientationGetterCallback);
516     bindProperty("clickPointX", &WebAXObjectProxy::clickPointXGetterCallback);
517     bindProperty("clickPointY", &WebAXObjectProxy::clickPointYGetterCallback);
518     bindProperty("rowCount", &WebAXObjectProxy::rowCountGetterCallback);
519     bindProperty("columnCount", &WebAXObjectProxy::columnCountGetterCallback);
520     bindProperty("isClickable", &WebAXObjectProxy::isClickableGetterCallback);
521 
522     //
523     // Methods
524     //
525 
526     bindMethod("allAttributes", &WebAXObjectProxy::allAttributesCallback);
527     bindMethod("attributesOfChildren", &WebAXObjectProxy::attributesOfChildrenCallback);
528     bindMethod("lineForIndex", &WebAXObjectProxy::lineForIndexCallback);
529     bindMethod("boundsForRange", &WebAXObjectProxy::boundsForRangeCallback);
530     bindMethod("childAtIndex", &WebAXObjectProxy::childAtIndexCallback);
531     bindMethod("elementAtPoint", &WebAXObjectProxy::elementAtPointCallback);
532     bindMethod("tableHeader", &WebAXObjectProxy::tableHeaderCallback);
533     bindMethod("rowIndexRange", &WebAXObjectProxy::rowIndexRangeCallback);
534     bindMethod("columnIndexRange", &WebAXObjectProxy::columnIndexRangeCallback);
535     bindMethod("cellForColumnAndRow", &WebAXObjectProxy::cellForColumnAndRowCallback);
536     bindMethod("titleUIElement", &WebAXObjectProxy::titleUIElementCallback);
537     bindMethod("setSelectedTextRange", &WebAXObjectProxy::setSelectedTextRangeCallback);
538     bindMethod("isAttributeSettable", &WebAXObjectProxy::isAttributeSettableCallback);
539     bindMethod("isPressActionSupported", &WebAXObjectProxy::isPressActionSupportedCallback);
540     bindMethod("isIncrementActionSupported", &WebAXObjectProxy::isIncrementActionSupportedCallback);
541     bindMethod("isDecrementActionSupported", &WebAXObjectProxy::isDecrementActionSupportedCallback);
542     bindMethod("parentElement", &WebAXObjectProxy::parentElementCallback);
543     bindMethod("increment", &WebAXObjectProxy::incrementCallback);
544     bindMethod("decrement", &WebAXObjectProxy::decrementCallback);
545     bindMethod("showMenu", &WebAXObjectProxy::showMenuCallback);
546     bindMethod("press", &WebAXObjectProxy::pressCallback);
547     bindMethod("isEqual", &WebAXObjectProxy::isEqualCallback);
548     bindMethod("addNotificationListener", &WebAXObjectProxy::addNotificationListenerCallback);
549     bindMethod("removeNotificationListener", &WebAXObjectProxy::removeNotificationListenerCallback);
550     bindMethod("takeFocus", &WebAXObjectProxy::takeFocusCallback);
551     bindMethod("scrollToMakeVisible", &WebAXObjectProxy::scrollToMakeVisibleCallback);
552     bindMethod("scrollToMakeVisibleWithSubFocus", &WebAXObjectProxy::scrollToMakeVisibleWithSubFocusCallback);
553     bindMethod("scrollToGlobalPoint", &WebAXObjectProxy::scrollToGlobalPointCallback);
554     bindMethod("wordStart", &WebAXObjectProxy::wordStartCallback);
555     bindMethod("wordEnd", &WebAXObjectProxy::wordEndCallback);
556 
557     bindFallbackMethod(&WebAXObjectProxy::fallbackCallback);
558 }
559 
getChildAtIndex(unsigned index)560 WebAXObjectProxy* WebAXObjectProxy::getChildAtIndex(unsigned index)
561 {
562     return m_factory->getOrCreate(accessibilityObject().childAt(index));
563 }
564 
isEqual(const blink::WebAXObject & other)565 bool WebAXObjectProxy::isEqual(const blink::WebAXObject& other)
566 {
567     return accessibilityObject().equals(other);
568 }
569 
notificationReceived(const char * notificationName)570 void WebAXObjectProxy::notificationReceived(const char* notificationName)
571 {
572     size_t callbackCount = m_notificationCallbacks.size();
573     for (size_t i = 0; i < callbackCount; i++) {
574         CppVariant notificationNameArgument;
575         notificationNameArgument.set(notificationName);
576         CppVariant invokeResult;
577         m_notificationCallbacks[i].invokeDefault(&notificationNameArgument, 1, invokeResult);
578     }
579 }
580 
581 //
582 // Properties
583 //
584 
roleGetterCallback(CppVariant * result)585 void WebAXObjectProxy::roleGetterCallback(CppVariant* result)
586 {
587     result->set(getRole(accessibilityObject()));
588 }
589 
titleGetterCallback(CppVariant * result)590 void WebAXObjectProxy::titleGetterCallback(CppVariant* result)
591 {
592     result->set(getTitle(accessibilityObject()));
593 }
594 
descriptionGetterCallback(CppVariant * result)595 void WebAXObjectProxy::descriptionGetterCallback(CppVariant* result)
596 {
597     result->set(getDescription(accessibilityObject()));
598 }
599 
helpTextGetterCallback(CppVariant * result)600 void WebAXObjectProxy::helpTextGetterCallback(CppVariant* result)
601 {
602     result->set(getHelpText(accessibilityObject()));
603 }
604 
stringValueGetterCallback(CppVariant * result)605 void WebAXObjectProxy::stringValueGetterCallback(CppVariant* result)
606 {
607     result->set(getStringValue(accessibilityObject()));
608 }
609 
xGetterCallback(CppVariant * result)610 void WebAXObjectProxy::xGetterCallback(CppVariant* result)
611 {
612     result->set(accessibilityObject().boundingBoxRect().x);
613 }
614 
yGetterCallback(CppVariant * result)615 void WebAXObjectProxy::yGetterCallback(CppVariant* result)
616 {
617     result->set(accessibilityObject().boundingBoxRect().y);
618 }
619 
widthGetterCallback(CppVariant * result)620 void WebAXObjectProxy::widthGetterCallback(CppVariant* result)
621 {
622     result->set(accessibilityObject().boundingBoxRect().width);
623 }
624 
heightGetterCallback(CppVariant * result)625 void WebAXObjectProxy::heightGetterCallback(CppVariant* result)
626 {
627     result->set(accessibilityObject().boundingBoxRect().height);
628 }
629 
intValueGetterCallback(CppVariant * result)630 void WebAXObjectProxy::intValueGetterCallback(CppVariant* result)
631 {
632     if (accessibilityObject().supportsRangeValue())
633         result->set(accessibilityObject().valueForRange());
634     else if (accessibilityObject().role() == WebAXRoleHeading)
635         result->set(accessibilityObject().headingLevel());
636     else
637         result->set(atoi(accessibilityObject().stringValue().utf8().data()));
638 }
639 
minValueGetterCallback(CppVariant * result)640 void WebAXObjectProxy::minValueGetterCallback(CppVariant* result)
641 {
642     result->set(accessibilityObject().minValueForRange());
643 }
644 
maxValueGetterCallback(CppVariant * result)645 void WebAXObjectProxy::maxValueGetterCallback(CppVariant* result)
646 {
647     result->set(accessibilityObject().maxValueForRange());
648 }
649 
valueDescriptionGetterCallback(CppVariant * result)650 void WebAXObjectProxy::valueDescriptionGetterCallback(CppVariant* result)
651 {
652     result->set(getValueDescription(accessibilityObject()));
653 }
654 
childrenCountGetterCallback(CppVariant * result)655 void WebAXObjectProxy::childrenCountGetterCallback(CppVariant* result)
656 {
657     int count = 1; // Root object always has only one child, the WebView.
658     if (!isRoot())
659         count = accessibilityObject().childCount();
660     result->set(count);
661 }
662 
insertionPointLineNumberGetterCallback(CppVariant * result)663 void WebAXObjectProxy::insertionPointLineNumberGetterCallback(CppVariant* result)
664 {
665     if (!accessibilityObject().isFocused()) {
666         result->set(-1);
667         return;
668     }
669 
670     int lineNumber = accessibilityObject().selectionEndLineNumber();
671     result->set(lineNumber);
672 }
673 
selectedTextRangeGetterCallback(CppVariant * result)674 void WebAXObjectProxy::selectedTextRangeGetterCallback(CppVariant* result)
675 {
676     unsigned selectionStart = accessibilityObject().selectionStart();
677     unsigned selectionEnd = accessibilityObject().selectionEnd();
678     char buffer[100];
679     snprintf(buffer, sizeof(buffer), "{%d, %d}", selectionStart, selectionEnd - selectionStart);
680 
681     result->set(std::string(buffer));
682 }
683 
isEnabledGetterCallback(CppVariant * result)684 void WebAXObjectProxy::isEnabledGetterCallback(CppVariant* result)
685 {
686     result->set(accessibilityObject().isEnabled());
687 }
688 
isRequiredGetterCallback(CppVariant * result)689 void WebAXObjectProxy::isRequiredGetterCallback(CppVariant* result)
690 {
691     result->set(accessibilityObject().isRequired());
692 }
693 
isFocusedGetterCallback(CppVariant * result)694 void WebAXObjectProxy::isFocusedGetterCallback(CppVariant* result)
695 {
696     result->set(accessibilityObject().isFocused());
697 }
698 
isFocusableGetterCallback(CppVariant * result)699 void WebAXObjectProxy::isFocusableGetterCallback(CppVariant* result)
700 {
701     result->set(accessibilityObject().canSetFocusAttribute());
702 }
703 
isSelectedGetterCallback(CppVariant * result)704 void WebAXObjectProxy::isSelectedGetterCallback(CppVariant* result)
705 {
706     result->set(accessibilityObject().isSelected());
707 }
708 
isSelectableGetterCallback(CppVariant * result)709 void WebAXObjectProxy::isSelectableGetterCallback(CppVariant* result)
710 {
711     result->set(accessibilityObject().canSetSelectedAttribute());
712 }
713 
isMultiSelectableGetterCallback(CppVariant * result)714 void WebAXObjectProxy::isMultiSelectableGetterCallback(CppVariant* result)
715 {
716     result->set(accessibilityObject().isMultiSelectable());
717 }
718 
isSelectedOptionActiveGetterCallback(CppVariant * result)719 void WebAXObjectProxy::isSelectedOptionActiveGetterCallback(CppVariant* result)
720 {
721     result->set(accessibilityObject().isSelectedOptionActive());
722 }
723 
isExpandedGetterCallback(CppVariant * result)724 void WebAXObjectProxy::isExpandedGetterCallback(CppVariant* result)
725 {
726     result->set(!accessibilityObject().isCollapsed());
727 }
728 
isCheckedGetterCallback(CppVariant * result)729 void WebAXObjectProxy::isCheckedGetterCallback(CppVariant* result)
730 {
731     result->set(accessibilityObject().isChecked());
732 }
733 
isVisibleGetterCallback(CppVariant * result)734 void WebAXObjectProxy::isVisibleGetterCallback(CppVariant* result)
735 {
736     result->set(accessibilityObject().isVisible());
737 }
738 
isOffScreenGetterCallback(CppVariant * result)739 void WebAXObjectProxy::isOffScreenGetterCallback(CppVariant* result)
740 {
741     result->set(accessibilityObject().isOffScreen());
742 }
743 
isCollapsedGetterCallback(CppVariant * result)744 void WebAXObjectProxy::isCollapsedGetterCallback(CppVariant* result)
745 {
746     result->set(accessibilityObject().isCollapsed());
747 }
748 
hasPopupGetterCallback(CppVariant * result)749 void WebAXObjectProxy::hasPopupGetterCallback(CppVariant* result)
750 {
751     result->set(accessibilityObject().ariaHasPopup());
752 }
753 
isValidGetterCallback(CppVariant * result)754 void WebAXObjectProxy::isValidGetterCallback(CppVariant* result)
755 {
756     result->set(!accessibilityObject().isDetached());
757 }
758 
isReadOnlyGetterCallback(CppVariant * result)759 void WebAXObjectProxy::isReadOnlyGetterCallback(CppVariant* result)
760 {
761     result->set(accessibilityObject().isReadOnly());
762 }
763 
orientationGetterCallback(CppVariant * result)764 void WebAXObjectProxy::orientationGetterCallback(CppVariant* result)
765 {
766     result->set(getOrientation(accessibilityObject()));
767 }
768 
clickPointXGetterCallback(CppVariant * result)769 void WebAXObjectProxy::clickPointXGetterCallback(CppVariant* result)
770 {
771     result->set(accessibilityObject().clickPoint().x);
772 }
773 
clickPointYGetterCallback(CppVariant * result)774 void WebAXObjectProxy::clickPointYGetterCallback(CppVariant* result)
775 {
776     result->set(accessibilityObject().clickPoint().y);
777 }
778 
rowCountGetterCallback(CppVariant * result)779 void WebAXObjectProxy::rowCountGetterCallback(CppVariant* result)
780 {
781     result->set(static_cast<int32_t>(accessibilityObject().rowCount()));
782 }
783 
columnCountGetterCallback(CppVariant * result)784 void WebAXObjectProxy::columnCountGetterCallback(CppVariant* result)
785 {
786     result->set(static_cast<int32_t>(accessibilityObject().columnCount()));
787 }
788 
isClickableGetterCallback(CppVariant * result)789 void WebAXObjectProxy::isClickableGetterCallback(CppVariant* result)
790 {
791     result->set(accessibilityObject().isClickable());
792 }
793 
794 //
795 // Methods
796 //
797 
allAttributesCallback(const CppArgumentList &,CppVariant * result)798 void WebAXObjectProxy::allAttributesCallback(const CppArgumentList&, CppVariant* result)
799 {
800     result->set(getAttributes(accessibilityObject()));
801 }
802 
attributesOfChildrenCallback(const CppArgumentList & arguments,CppVariant * result)803 void WebAXObjectProxy::attributesOfChildrenCallback(const CppArgumentList& arguments, CppVariant* result)
804 {
805     AttributesCollector collector;
806     unsigned size = accessibilityObject().childCount();
807     for (unsigned i = 0; i < size; ++i)
808         collector.collectAttributes(accessibilityObject().childAt(i));
809     result->set(collector.attributes());
810 }
811 
lineForIndexCallback(const CppArgumentList & arguments,CppVariant * result)812 void WebAXObjectProxy::lineForIndexCallback(const CppArgumentList& arguments, CppVariant* result)
813 {
814     if (!arguments.size() || !arguments[0].isNumber()) {
815         result->setNull();
816         return;
817     }
818 
819     int index = arguments[0].toInt32();
820 
821     WebVector<int> lineBreaks;
822     accessibilityObject().lineBreaks(lineBreaks);
823     int line = 0;
824     int vectorSize = static_cast<int>(lineBreaks.size());
825     while (line < vectorSize && lineBreaks[line] <= index)
826         line++;
827     result->set(line);
828 }
829 
boundsForRangeCallback(const CppArgumentList & arguments,CppVariant * result)830 void WebAXObjectProxy::boundsForRangeCallback(const CppArgumentList& arguments, CppVariant* result)
831 {
832     result->setNull();
833 
834     if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
835         return;
836 
837     if (accessibilityObject().role() != WebAXRoleStaticText)
838         return;
839 
840     int start = arguments[0].toInt32();
841     int end = arguments[1].toInt32();
842     int len = end - start;
843 
844     // Get the bounds for each character and union them into one large rectangle.
845     // This is just for testing so it doesn't need to be efficient.
846     WebRect bounds = boundsForCharacter(accessibilityObject(), start);
847     for (int i = 1; i < len; i++) {
848         WebRect next = boundsForCharacter(accessibilityObject(), start + i);
849         int right = std::max(bounds.x + bounds.width, next.x + next.width);
850         int bottom = std::max(bounds.y + bounds.height, next.y + next.height);
851         bounds.x = std::min(bounds.x, next.x);
852         bounds.y = std::min(bounds.y, next.y);
853         bounds.width = right - bounds.x;
854         bounds.height = bottom - bounds.y;
855     }
856 
857     char buffer[100];
858     snprintf(buffer, sizeof(buffer), "{x: %d, y: %d, width: %d, height: %d}", bounds.x, bounds.y, bounds.width, bounds.height);
859     result->set(string(buffer));
860 }
861 
childAtIndexCallback(const CppArgumentList & arguments,CppVariant * result)862 void WebAXObjectProxy::childAtIndexCallback(const CppArgumentList& arguments, CppVariant* result)
863 {
864     if (!arguments.size() || !arguments[0].isNumber()) {
865         result->setNull();
866         return;
867     }
868 
869     WebAXObjectProxy* child = getChildAtIndex(arguments[0].toInt32());
870     if (!child) {
871         result->setNull();
872         return;
873     }
874 
875     result->set(*(child->getAsCppVariant()));
876 }
877 
elementAtPointCallback(const CppArgumentList & arguments,CppVariant * result)878 void WebAXObjectProxy::elementAtPointCallback(const CppArgumentList& arguments, CppVariant* result)
879 {
880     result->setNull();
881 
882     if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
883         return;
884 
885     int x = arguments[0].toInt32();
886     int y = arguments[1].toInt32();
887     WebPoint point(x, y);
888     WebAXObject obj = accessibilityObject().hitTest(point);
889     if (obj.isNull())
890         return;
891 
892     result->set(*(m_factory->getOrCreate(obj)->getAsCppVariant()));
893 }
894 
tableHeaderCallback(const CppArgumentList &,CppVariant * result)895 void WebAXObjectProxy::tableHeaderCallback(const CppArgumentList&, CppVariant* result)
896 {
897     WebAXObject obj = accessibilityObject().headerContainerObject();
898     if (obj.isNull()) {
899         result->setNull();
900         return;
901     }
902 
903     result->set(*(m_factory->getOrCreate(obj)->getAsCppVariant()));
904 }
905 
rowIndexRangeCallback(const CppArgumentList &,CppVariant * result)906 void WebAXObjectProxy::rowIndexRangeCallback(const CppArgumentList&, CppVariant* result)
907 {
908     unsigned rowIndex = accessibilityObject().cellRowIndex();
909     unsigned rowSpan = accessibilityObject().cellRowSpan();
910     char buffer[100];
911     snprintf(buffer, sizeof(buffer), "{%d, %d}", rowIndex, rowSpan);
912     string value = buffer;
913     result->set(std::string(buffer));
914 }
915 
columnIndexRangeCallback(const CppArgumentList &,CppVariant * result)916 void WebAXObjectProxy::columnIndexRangeCallback(const CppArgumentList&, CppVariant* result)
917 {
918     unsigned columnIndex = accessibilityObject().cellColumnIndex();
919     unsigned columnSpan = accessibilityObject().cellColumnSpan();
920     char buffer[100];
921     snprintf(buffer, sizeof(buffer), "{%d, %d}", columnIndex, columnSpan);
922     result->set(std::string(buffer));
923 }
924 
cellForColumnAndRowCallback(const CppArgumentList & arguments,CppVariant * result)925 void WebAXObjectProxy::cellForColumnAndRowCallback(const CppArgumentList& arguments, CppVariant* result)
926 {
927     if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
928         return;
929 
930     int column = arguments[0].toInt32();
931     int row = arguments[1].toInt32();
932     WebAXObject obj = accessibilityObject().cellForColumnAndRow(column, row);
933     if (obj.isNull()) {
934         result->setNull();
935         return;
936     }
937 
938     result->set(*(m_factory->getOrCreate(obj)->getAsCppVariant()));
939 }
940 
titleUIElementCallback(const CppArgumentList &,CppVariant * result)941 void WebAXObjectProxy::titleUIElementCallback(const CppArgumentList&, CppVariant* result)
942 {
943     WebAXObject obj = accessibilityObject().titleUIElement();
944     if (obj.isNull()) {
945         result->setNull();
946         return;
947     }
948 
949     result->set(*(m_factory->getOrCreate(obj)->getAsCppVariant()));
950 }
951 
setSelectedTextRangeCallback(const CppArgumentList & arguments,CppVariant * result)952 void WebAXObjectProxy::setSelectedTextRangeCallback(const CppArgumentList&arguments, CppVariant* result)
953 {
954     result->setNull();
955     if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
956         return;
957 
958     int selectionStart = arguments[0].toInt32();
959     int selectionEnd = selectionStart + arguments[1].toInt32();
960     accessibilityObject().setSelectedTextRange(selectionStart, selectionEnd);
961 }
962 
isAttributeSettableCallback(const CppArgumentList & arguments,CppVariant * result)963 void WebAXObjectProxy::isAttributeSettableCallback(const CppArgumentList& arguments, CppVariant* result)
964 {
965     if (arguments.size() < 1 && !arguments[0].isString()) {
966         result->setNull();
967         return;
968     }
969 
970     string attribute = arguments[0].toString();
971     bool settable = false;
972     if (attribute == "AXValue")
973         settable = accessibilityObject().canSetValueAttribute();
974     result->set(settable);
975 }
976 
isPressActionSupportedCallback(const CppArgumentList &,CppVariant * result)977 void WebAXObjectProxy::isPressActionSupportedCallback(const CppArgumentList&, CppVariant* result)
978 {
979     result->set(accessibilityObject().canPress());
980 }
981 
isIncrementActionSupportedCallback(const CppArgumentList &,CppVariant * result)982 void WebAXObjectProxy::isIncrementActionSupportedCallback(const CppArgumentList&, CppVariant* result)
983 {
984     result->set(accessibilityObject().canIncrement());
985 }
986 
isDecrementActionSupportedCallback(const CppArgumentList &,CppVariant * result)987 void WebAXObjectProxy::isDecrementActionSupportedCallback(const CppArgumentList&, CppVariant* result)
988 {
989     result->set(accessibilityObject().canDecrement());
990 }
991 
parentElementCallback(const CppArgumentList &,CppVariant * result)992 void WebAXObjectProxy::parentElementCallback(const CppArgumentList&, CppVariant* result)
993 {
994     WebAXObject parentObject = accessibilityObject().parentObject();
995     while (parentObject.accessibilityIsIgnored())
996         parentObject = parentObject.parentObject();
997     WebAXObjectProxy* parent = m_factory->getOrCreate(parentObject);
998     if (!parent) {
999         result->setNull();
1000         return;
1001     }
1002 
1003     result->set(*(parent->getAsCppVariant()));
1004 }
1005 
incrementCallback(const CppArgumentList &,CppVariant * result)1006 void WebAXObjectProxy::incrementCallback(const CppArgumentList&, CppVariant* result)
1007 {
1008     accessibilityObject().increment();
1009     result->setNull();
1010 }
1011 
decrementCallback(const CppArgumentList &,CppVariant * result)1012 void WebAXObjectProxy::decrementCallback(const CppArgumentList&, CppVariant* result)
1013 {
1014     accessibilityObject().decrement();
1015     result->setNull();
1016 }
1017 
showMenuCallback(const CppArgumentList &,CppVariant * result)1018 void WebAXObjectProxy::showMenuCallback(const CppArgumentList&, CppVariant* result)
1019 {
1020     result->setNull();
1021 }
1022 
pressCallback(const CppArgumentList &,CppVariant * result)1023 void WebAXObjectProxy::pressCallback(const CppArgumentList&, CppVariant* result)
1024 {
1025     accessibilityObject().press();
1026     result->setNull();
1027 }
1028 
isEqualCallback(const CppArgumentList & arguments,CppVariant * result)1029 void WebAXObjectProxy::isEqualCallback(const CppArgumentList& arguments, CppVariant* result)
1030 {
1031     if (arguments.size() < 1 || !arguments[0].isObject()) {
1032         result->setNull();
1033         return;
1034     }
1035 
1036     result->set(arguments[0].isEqual(*getAsCppVariant()));
1037 }
1038 
addNotificationListenerCallback(const CppArgumentList & arguments,CppVariant * result)1039 void WebAXObjectProxy::addNotificationListenerCallback(const CppArgumentList& arguments, CppVariant* result)
1040 {
1041     if (arguments.size() < 1 || !arguments[0].isObject()) {
1042         result->setNull();
1043         return;
1044     }
1045 
1046     m_notificationCallbacks.push_back(arguments[0]);
1047     result->setNull();
1048 }
1049 
removeNotificationListenerCallback(const CppArgumentList &,CppVariant * result)1050 void WebAXObjectProxy::removeNotificationListenerCallback(const CppArgumentList&, CppVariant* result)
1051 {
1052     // FIXME: Implement this.
1053     result->setNull();
1054 }
1055 
takeFocusCallback(const CppArgumentList &,CppVariant * result)1056 void WebAXObjectProxy::takeFocusCallback(const CppArgumentList&, CppVariant* result)
1057 {
1058     accessibilityObject().setFocused(true);
1059     result->setNull();
1060 }
1061 
scrollToMakeVisibleCallback(const CppArgumentList &,CppVariant * result)1062 void WebAXObjectProxy::scrollToMakeVisibleCallback(const CppArgumentList&, CppVariant* result)
1063 {
1064     accessibilityObject().scrollToMakeVisible();
1065     result->setNull();
1066 }
1067 
scrollToMakeVisibleWithSubFocusCallback(const CppArgumentList & arguments,CppVariant * result)1068 void WebAXObjectProxy::scrollToMakeVisibleWithSubFocusCallback(const CppArgumentList& arguments, CppVariant* result)
1069 {
1070     result->setNull();
1071 
1072     if (arguments.size() != 4
1073         || !arguments[0].isNumber()
1074         || !arguments[1].isNumber()
1075         || !arguments[2].isNumber()
1076         || !arguments[3].isNumber())
1077         return;
1078 
1079     int x = arguments[0].toInt32();
1080     int y = arguments[1].toInt32();
1081     int width = arguments[2].toInt32();
1082     int height = arguments[3].toInt32();
1083     accessibilityObject().scrollToMakeVisibleWithSubFocus(WebRect(x, y, width, height));
1084     result->setNull();
1085 }
1086 
scrollToGlobalPointCallback(const CppArgumentList & arguments,CppVariant * result)1087 void WebAXObjectProxy::scrollToGlobalPointCallback(const CppArgumentList& arguments, CppVariant* result)
1088 {
1089     result->setNull();
1090 
1091     if (arguments.size() != 2
1092         || !arguments[0].isNumber()
1093         || !arguments[1].isNumber())
1094         return;
1095 
1096     int x = arguments[0].toInt32();
1097     int y = arguments[1].toInt32();
1098 
1099     accessibilityObject().scrollToGlobalPoint(WebPoint(x, y));
1100     result->setNull();
1101 }
1102 
wordStartCallback(const CppArgumentList & arguments,CppVariant * result)1103 void WebAXObjectProxy::wordStartCallback(const CppArgumentList& arguments, CppVariant* result)
1104 {
1105     result->setNull();
1106 
1107     if (arguments.size() != 1 || !arguments[0].isNumber())
1108         return;
1109 
1110     if (accessibilityObject().role() != WebAXRoleStaticText)
1111         return;
1112 
1113     int characterIndex = arguments[0].toInt32();
1114     int wordStart, wordEnd;
1115     getBoundariesForOneWord(accessibilityObject(), characterIndex, wordStart, wordEnd);
1116     result->set(wordStart);
1117 }
1118 
wordEndCallback(const CppArgumentList & arguments,CppVariant * result)1119 void WebAXObjectProxy::wordEndCallback(const CppArgumentList& arguments, CppVariant* result)
1120 {
1121     result->setNull();
1122 
1123     if (arguments.size() != 1 || !arguments[0].isNumber())
1124         return;
1125 
1126     if (accessibilityObject().role() != WebAXRoleStaticText)
1127         return;
1128 
1129     int characterIndex = arguments[0].toInt32();
1130     int wordStart, wordEnd;
1131     getBoundariesForOneWord(accessibilityObject(), characterIndex, wordStart, wordEnd);
1132     result->set(wordEnd);
1133 }
1134 
fallbackCallback(const CppArgumentList &,CppVariant * result)1135 void WebAXObjectProxy::fallbackCallback(const CppArgumentList &, CppVariant* result)
1136 {
1137     result->setNull();
1138 }
1139 
RootWebAXObjectProxy(const WebAXObject & object,Factory * factory)1140 RootWebAXObjectProxy::RootWebAXObjectProxy(const WebAXObject &object, Factory *factory)
1141     : WebAXObjectProxy(object, factory) { }
1142 
getChildAtIndex(unsigned index)1143 WebAXObjectProxy* RootWebAXObjectProxy::getChildAtIndex(unsigned index)
1144 {
1145     if (index)
1146         return 0;
1147 
1148     return factory()->getOrCreate(accessibilityObject());
1149 }
1150 
1151 
~WebAXObjectProxyList()1152 WebAXObjectProxyList ::~WebAXObjectProxyList()
1153 {
1154     clear();
1155 }
1156 
clear()1157 void WebAXObjectProxyList::clear()
1158 {
1159     for (ElementList::iterator i = m_elements.begin(); i != m_elements.end(); ++i)
1160         delete (*i);
1161     m_elements.clear();
1162 }
1163 
getOrCreate(const WebAXObject & object)1164 WebAXObjectProxy* WebAXObjectProxyList::getOrCreate(const WebAXObject& object)
1165 {
1166     if (object.isNull())
1167         return 0;
1168 
1169     size_t elementCount = m_elements.size();
1170     for (size_t i = 0; i < elementCount; i++) {
1171         if (m_elements[i]->isEqual(object))
1172             return m_elements[i];
1173     }
1174 
1175     WebAXObjectProxy* element = new WebAXObjectProxy(object, this);
1176     m_elements.push_back(element);
1177     return element;
1178 }
1179 
createRoot(const WebAXObject & object)1180 WebAXObjectProxy* WebAXObjectProxyList::createRoot(const WebAXObject& object)
1181 {
1182     WebAXObjectProxy* element = new RootWebAXObjectProxy(object, this);
1183     m_elements.push_back(element);
1184     return element;
1185 }
1186 
1187 }
1188