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 "AccessibilityUIElementChromium.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 #include "public/web/WebAccessibilityObject.h" 39 40 using namespace WebKit; 41 using namespace std; 42 43 namespace WebTestRunner { 44 45 namespace { 46 47 // Map role value to string, matching Safari/Mac platform implementation to 48 // avoid rebaselining layout tests. 49 string roleToString(WebAccessibilityRole role) 50 { 51 string result = "AXRole: AX"; 52 switch (role) { 53 case WebAccessibilityRoleButton: 54 return result.append("Button"); 55 case WebAccessibilityRoleRadioButton: 56 return result.append("RadioButton"); 57 case WebAccessibilityRoleCheckBox: 58 return result.append("CheckBox"); 59 case WebAccessibilityRoleSlider: 60 return result.append("Slider"); 61 case WebAccessibilityRoleTabGroup: 62 return result.append("TabGroup"); 63 case WebAccessibilityRoleTextField: 64 return result.append("TextField"); 65 case WebAccessibilityRoleStaticText: 66 return result.append("StaticText"); 67 case WebAccessibilityRoleTextArea: 68 return result.append("TextArea"); 69 case WebAccessibilityRoleScrollArea: 70 return result.append("ScrollArea"); 71 case WebAccessibilityRolePopUpButton: 72 return result.append("PopUpButton"); 73 case WebAccessibilityRoleMenuButton: 74 return result.append("MenuButton"); 75 case WebAccessibilityRoleTable: 76 return result.append("Table"); 77 case WebAccessibilityRoleApplication: 78 return result.append("Application"); 79 case WebAccessibilityRoleGroup: 80 return result.append("Group"); 81 case WebAccessibilityRoleRadioGroup: 82 return result.append("RadioGroup"); 83 case WebAccessibilityRoleList: 84 return result.append("List"); 85 case WebAccessibilityRoleScrollBar: 86 return result.append("ScrollBar"); 87 case WebAccessibilityRoleValueIndicator: 88 return result.append("ValueIndicator"); 89 case WebAccessibilityRoleImage: 90 return result.append("Image"); 91 case WebAccessibilityRoleMenuBar: 92 return result.append("MenuBar"); 93 case WebAccessibilityRoleMenu: 94 return result.append("Menu"); 95 case WebAccessibilityRoleMenuItem: 96 return result.append("MenuItem"); 97 case WebAccessibilityRoleColumn: 98 return result.append("Column"); 99 case WebAccessibilityRoleRow: 100 return result.append("Row"); 101 case WebAccessibilityRoleToolbar: 102 return result.append("Toolbar"); 103 case WebAccessibilityRoleBusyIndicator: 104 return result.append("BusyIndicator"); 105 case WebAccessibilityRoleProgressIndicator: 106 return result.append("ProgressIndicator"); 107 case WebAccessibilityRoleWindow: 108 return result.append("Window"); 109 case WebAccessibilityRoleDrawer: 110 return result.append("Drawer"); 111 case WebAccessibilityRoleSystemWide: 112 return result.append("SystemWide"); 113 case WebAccessibilityRoleOutline: 114 return result.append("Outline"); 115 case WebAccessibilityRoleIncrementor: 116 return result.append("Incrementor"); 117 case WebAccessibilityRoleBrowser: 118 return result.append("Browser"); 119 case WebAccessibilityRoleComboBox: 120 return result.append("ComboBox"); 121 case WebAccessibilityRoleSplitGroup: 122 return result.append("SplitGroup"); 123 case WebAccessibilityRoleSplitter: 124 return result.append("Splitter"); 125 case WebAccessibilityRoleColorWell: 126 return result.append("ColorWell"); 127 case WebAccessibilityRoleGrowArea: 128 return result.append("GrowArea"); 129 case WebAccessibilityRoleSheet: 130 return result.append("Sheet"); 131 case WebAccessibilityRoleHelpTag: 132 return result.append("HelpTag"); 133 case WebAccessibilityRoleMatte: 134 return result.append("Matte"); 135 case WebAccessibilityRoleRuler: 136 return result.append("Ruler"); 137 case WebAccessibilityRoleRulerMarker: 138 return result.append("RulerMarker"); 139 case WebAccessibilityRoleLink: 140 return result.append("Link"); 141 case WebAccessibilityRoleDisclosureTriangle: 142 return result.append("DisclosureTriangle"); 143 case WebAccessibilityRoleGrid: 144 return result.append("Grid"); 145 case WebAccessibilityRoleCell: 146 return result.append("Cell"); 147 case WebAccessibilityRoleColumnHeader: 148 return result.append("ColumnHeader"); 149 case WebAccessibilityRoleRowHeader: 150 return result.append("RowHeader"); 151 case WebAccessibilityRoleWebCoreLink: 152 // Maps to Link role. 153 return result.append("Link"); 154 case WebAccessibilityRoleImageMapLink: 155 return result.append("ImageMapLink"); 156 case WebAccessibilityRoleImageMap: 157 return result.append("ImageMap"); 158 case WebAccessibilityRoleListMarker: 159 return result.append("ListMarker"); 160 case WebAccessibilityRoleWebArea: 161 return result.append("WebArea"); 162 case WebAccessibilityRoleHeading: 163 return result.append("Heading"); 164 case WebAccessibilityRoleListBox: 165 return result.append("ListBox"); 166 case WebAccessibilityRoleListBoxOption: 167 return result.append("ListBoxOption"); 168 case WebAccessibilityRoleTableHeaderContainer: 169 return result.append("TableHeaderContainer"); 170 case WebAccessibilityRoleDefinition: 171 return result.append("Definition"); 172 case WebAccessibilityRoleDescriptionListTerm: 173 return result.append("DescriptionListTerm"); 174 case WebAccessibilityRoleDescriptionListDetail: 175 return result.append("DescriptionListDetail"); 176 case WebAccessibilityRoleAnnotation: 177 return result.append("Annotation"); 178 case WebAccessibilityRoleSliderThumb: 179 return result.append("SliderThumb"); 180 case WebAccessibilityRoleLandmarkApplication: 181 return result.append("LandmarkApplication"); 182 case WebAccessibilityRoleLandmarkBanner: 183 return result.append("LandmarkBanner"); 184 case WebAccessibilityRoleLandmarkComplementary: 185 return result.append("LandmarkComplementary"); 186 case WebAccessibilityRoleLandmarkContentInfo: 187 return result.append("LandmarkContentInfo"); 188 case WebAccessibilityRoleLandmarkMain: 189 return result.append("LandmarkMain"); 190 case WebAccessibilityRoleLandmarkNavigation: 191 return result.append("LandmarkNavigation"); 192 case WebAccessibilityRoleLandmarkSearch: 193 return result.append("LandmarkSearch"); 194 case WebAccessibilityRoleApplicationLog: 195 return result.append("ApplicationLog"); 196 case WebAccessibilityRoleApplicationMarquee: 197 return result.append("ApplicationMarquee"); 198 case WebAccessibilityRoleApplicationStatus: 199 return result.append("ApplicationStatus"); 200 case WebAccessibilityRoleApplicationTimer: 201 return result.append("ApplicationTimer"); 202 case WebAccessibilityRoleDocument: 203 return result.append("Document"); 204 case WebAccessibilityRoleDocumentArticle: 205 return result.append("DocumentArticle"); 206 case WebAccessibilityRoleDocumentNote: 207 return result.append("DocumentNote"); 208 case WebAccessibilityRoleDocumentRegion: 209 return result.append("DocumentRegion"); 210 case WebAccessibilityRoleUserInterfaceTooltip: 211 return result.append("UserInterfaceTooltip"); 212 case WebAccessibilityRoleToggleButton: 213 return result.append("ToggleButton"); 214 case WebAccessibilityRoleCanvas: 215 return result.append("Canvas"); 216 case WebAccessibilityRoleParagraph: 217 return result.append("Paragraph"); 218 case WebAccessibilityRoleDiv: 219 return result.append("Div"); 220 case WebAccessibilityRoleLabel: 221 return result.append("Label"); 222 case WebAccessibilityRoleForm: 223 return result.append("Form"); 224 case WebAccessibilityRoleHorizontalRule: 225 return result.append("HorizontalRule"); 226 case WebAccessibilityRoleLegend: 227 return result.append("Legend"); 228 case WebAccessibilityRoleApplicationAlert: 229 return result.append("Alert"); 230 case WebAccessibilityRoleApplicationAlertDialog: 231 return result.append("AlertDialog"); 232 case WebAccessibilityRoleApplicationDialog: 233 return result.append("ApplicationDialog"); 234 case WebAccessibilityRoleDirectory: 235 return result.append("Directory"); 236 case WebAccessibilityRoleDocumentMath: 237 return result.append("Math"); 238 case WebAccessibilityRoleEditableText: 239 return result.append("EditableText"); 240 case WebAccessibilityRoleFooter: 241 return result.append("Footer"); 242 case WebAccessibilityRoleIgnored: 243 return result.append("Ignored"); 244 case WebAccessibilityRoleListItem: 245 return result.append("ListItem"); 246 case WebAccessibilityRoleMenuListPopup: 247 return result.append("MenuListPopup"); 248 case WebAccessibilityRoleMenuListOption: 249 return result.append("MenuListOption"); 250 case WebAccessibilityRolePresentational: 251 return result.append("Presentational"); 252 case WebAccessibilityRoleSpinButton: 253 return result.append("SpinButton"); 254 case WebAccessibilityRoleSpinButtonPart: 255 return result.append("SpinButtonPart"); 256 case WebAccessibilityRoleTabList: 257 return result.append("TabList"); 258 case WebAccessibilityRoleTabPanel: 259 return result.append("TabPanel"); 260 case WebAccessibilityRoleTab: 261 return result.append("Tab"); 262 case WebAccessibilityRoleTreeRole: 263 return result.append("Tree"); 264 case WebAccessibilityRoleTreeGrid: 265 return result.append("TreeGrid"); 266 case WebAccessibilityRoleTreeItemRole: 267 return result.append("TreeItem"); 268 case WebAccessibilityRoleUnknown: 269 default: 270 return result.append("Unknown"); 271 } 272 } 273 274 string getDescription(const WebAccessibilityObject& object) 275 { 276 string description = object.accessibilityDescription().utf8(); 277 return description.insert(0, "AXDescription: "); 278 } 279 280 string getHelpText(const WebAccessibilityObject& object) 281 { 282 string helpText = object.helpText().utf8(); 283 return helpText.insert(0, "AXHelp: "); 284 } 285 286 string getStringValue(const WebAccessibilityObject& object) 287 { 288 string value; 289 if (object.roleValue() == WebAccessibilityRoleColorWell) { 290 int r, g, b; 291 char buffer[100]; 292 object.colorValue(r, g, b); 293 snprintf(buffer, sizeof(buffer), "rgb %7.5f %7.5f %7.5f 1", r / 255., g / 255., b / 255.); 294 value = buffer; 295 } else 296 value = object.stringValue().utf8(); 297 return value.insert(0, "AXValue: "); 298 } 299 300 string getRole(const WebAccessibilityObject& object) 301 { 302 string roleString = roleToString(object.roleValue()); 303 304 // Special-case canvas with fallback content because Chromium wants to 305 // treat this as essentially a separate role that it can map differently depending 306 // on the platform. 307 if (object.roleValue() == WebAccessibilityRoleCanvas && object.canvasHasFallbackContent()) 308 roleString += "WithFallbackContent"; 309 310 return roleString; 311 } 312 313 string getTitle(const WebAccessibilityObject& object) 314 { 315 string title = object.title().utf8(); 316 return title.insert(0, "AXTitle: "); 317 } 318 319 string getOrientation(const WebAccessibilityObject& object) 320 { 321 if (object.isVertical()) 322 return "AXOrientation: AXVerticalOrientation"; 323 324 return "AXOrientation: AXHorizontalOrientation"; 325 } 326 327 string getValueDescription(const WebAccessibilityObject& object) 328 { 329 string valueDescription = object.valueDescription().utf8(); 330 return valueDescription.insert(0, "AXValueDescription: "); 331 } 332 333 string getAttributes(const WebAccessibilityObject& object) 334 { 335 // FIXME: Concatenate all attributes of the AccessibilityObject. 336 string attributes(getTitle(object)); 337 attributes.append("\n"); 338 attributes.append(getRole(object)); 339 attributes.append("\n"); 340 attributes.append(getDescription(object)); 341 return attributes; 342 } 343 344 345 // Collects attributes into a string, delimited by dashes. Used by all methods 346 // that output lists of attributes: attributesOfLinkedUIElementsCallback, 347 // AttributesOfChildrenCallback, etc. 348 class AttributesCollector { 349 public: 350 void collectAttributes(const WebAccessibilityObject& object) 351 { 352 m_attributes.append("\n------------\n"); 353 m_attributes.append(getAttributes(object)); 354 } 355 356 string attributes() const { return m_attributes; } 357 358 private: 359 string m_attributes; 360 }; 361 362 } 363 364 AccessibilityUIElement::AccessibilityUIElement(const WebAccessibilityObject& object, Factory* factory) 365 : m_accessibilityObject(object) 366 , m_factory(factory) 367 { 368 369 WEBKIT_ASSERT(factory); 370 371 // 372 // Properties 373 // 374 375 bindProperty("role", &AccessibilityUIElement::roleGetterCallback); 376 bindProperty("title", &AccessibilityUIElement::titleGetterCallback); 377 bindProperty("description", &AccessibilityUIElement::descriptionGetterCallback); 378 bindProperty("helpText", &AccessibilityUIElement::helpTextGetterCallback); 379 bindProperty("stringValue", &AccessibilityUIElement::stringValueGetterCallback); 380 bindProperty("x", &AccessibilityUIElement::xGetterCallback); 381 bindProperty("y", &AccessibilityUIElement::yGetterCallback); 382 bindProperty("width", &AccessibilityUIElement::widthGetterCallback); 383 bindProperty("height", &AccessibilityUIElement::heightGetterCallback); 384 bindProperty("intValue", &AccessibilityUIElement::intValueGetterCallback); 385 bindProperty("minValue", &AccessibilityUIElement::minValueGetterCallback); 386 bindProperty("maxValue", &AccessibilityUIElement::maxValueGetterCallback); 387 bindProperty("valueDescription", &AccessibilityUIElement::valueDescriptionGetterCallback); 388 bindProperty("childrenCount", &AccessibilityUIElement::childrenCountGetterCallback); 389 bindProperty("insertionPointLineNumber", &AccessibilityUIElement::insertionPointLineNumberGetterCallback); 390 bindProperty("selectedTextRange", &AccessibilityUIElement::selectedTextRangeGetterCallback); 391 bindProperty("isEnabled", &AccessibilityUIElement::isEnabledGetterCallback); 392 bindProperty("isRequired", &AccessibilityUIElement::isRequiredGetterCallback); 393 bindProperty("isFocused", &AccessibilityUIElement::isFocusedGetterCallback); 394 bindProperty("isFocusable", &AccessibilityUIElement::isFocusableGetterCallback); 395 bindProperty("isSelected", &AccessibilityUIElement::isSelectedGetterCallback); 396 bindProperty("isSelectable", &AccessibilityUIElement::isSelectableGetterCallback); 397 bindProperty("isMultiSelectable", &AccessibilityUIElement::isMultiSelectableGetterCallback); 398 bindProperty("isSelectedOptionActive", &AccessibilityUIElement::isSelectedOptionActiveGetterCallback); 399 bindProperty("isExpanded", &AccessibilityUIElement::isExpandedGetterCallback); 400 bindProperty("isChecked", &AccessibilityUIElement::isCheckedGetterCallback); 401 bindProperty("isVisible", &AccessibilityUIElement::isVisibleGetterCallback); 402 bindProperty("isOffScreen", &AccessibilityUIElement::isOffScreenGetterCallback); 403 bindProperty("isCollapsed", &AccessibilityUIElement::isCollapsedGetterCallback); 404 bindProperty("hasPopup", &AccessibilityUIElement::hasPopupGetterCallback); 405 bindProperty("isValid", &AccessibilityUIElement::isValidGetterCallback); 406 bindProperty("isReadOnly", &AccessibilityUIElement::isReadOnlyGetterCallback); 407 bindProperty("orientation", &AccessibilityUIElement::orientationGetterCallback); 408 bindProperty("clickPointX", &AccessibilityUIElement::clickPointXGetterCallback); 409 bindProperty("clickPointY", &AccessibilityUIElement::clickPointYGetterCallback); 410 bindProperty("rowCount", &AccessibilityUIElement::rowCountGetterCallback); 411 bindProperty("columnCount", &AccessibilityUIElement::columnCountGetterCallback); 412 413 // 414 // Methods 415 // 416 417 bindMethod("allAttributes", &AccessibilityUIElement::allAttributesCallback); 418 bindMethod("attributesOfLinkedUIElements", &AccessibilityUIElement::attributesOfLinkedUIElementsCallback); 419 bindMethod("attributesOfDocumentLinks", &AccessibilityUIElement::attributesOfDocumentLinksCallback); 420 bindMethod("attributesOfChildren", &AccessibilityUIElement::attributesOfChildrenCallback); 421 bindMethod("lineForIndex", &AccessibilityUIElement::lineForIndexCallback); 422 bindMethod("boundsForRange", &AccessibilityUIElement::boundsForRangeCallback); 423 bindMethod("stringForRange", &AccessibilityUIElement::stringForRangeCallback); 424 bindMethod("childAtIndex", &AccessibilityUIElement::childAtIndexCallback); 425 bindMethod("elementAtPoint", &AccessibilityUIElement::elementAtPointCallback); 426 bindMethod("attributesOfColumnHeaders", &AccessibilityUIElement::attributesOfColumnHeadersCallback); 427 bindMethod("attributesOfRowHeaders", &AccessibilityUIElement::attributesOfRowHeadersCallback); 428 bindMethod("attributesOfColumns", &AccessibilityUIElement::attributesOfColumnsCallback); 429 bindMethod("attributesOfRows", &AccessibilityUIElement::attributesOfRowsCallback); 430 bindMethod("attributesOfVisibleCells", &AccessibilityUIElement::attributesOfVisibleCellsCallback); 431 bindMethod("attributesOfHeader", &AccessibilityUIElement::attributesOfHeaderCallback); 432 bindMethod("tableHeader", &AccessibilityUIElement::tableHeaderCallback); 433 bindMethod("indexInTable", &AccessibilityUIElement::indexInTableCallback); 434 bindMethod("rowIndexRange", &AccessibilityUIElement::rowIndexRangeCallback); 435 bindMethod("columnIndexRange", &AccessibilityUIElement::columnIndexRangeCallback); 436 bindMethod("cellForColumnAndRow", &AccessibilityUIElement::cellForColumnAndRowCallback); 437 bindMethod("titleUIElement", &AccessibilityUIElement::titleUIElementCallback); 438 bindMethod("setSelectedTextRange", &AccessibilityUIElement::setSelectedTextRangeCallback); 439 bindMethod("attributeValue", &AccessibilityUIElement::attributeValueCallback); 440 bindMethod("isAttributeSettable", &AccessibilityUIElement::isAttributeSettableCallback); 441 bindMethod("isPressActionSupported", &AccessibilityUIElement::isPressActionSupportedCallback); 442 bindMethod("isIncrementActionSupported", &AccessibilityUIElement::isIncrementActionSupportedCallback); 443 bindMethod("isDecrementActionSupported", &AccessibilityUIElement::isDecrementActionSupportedCallback); 444 bindMethod("parentElement", &AccessibilityUIElement::parentElementCallback); 445 bindMethod("increment", &AccessibilityUIElement::incrementCallback); 446 bindMethod("decrement", &AccessibilityUIElement::decrementCallback); 447 bindMethod("showMenu", &AccessibilityUIElement::showMenuCallback); 448 bindMethod("press", &AccessibilityUIElement::pressCallback); 449 bindMethod("isEqual", &AccessibilityUIElement::isEqualCallback); 450 bindMethod("addNotificationListener", &AccessibilityUIElement::addNotificationListenerCallback); 451 bindMethod("removeNotificationListener", &AccessibilityUIElement::removeNotificationListenerCallback); 452 bindMethod("takeFocus", &AccessibilityUIElement::takeFocusCallback); 453 bindMethod("scrollToMakeVisible", &AccessibilityUIElement::scrollToMakeVisibleCallback); 454 bindMethod("scrollToMakeVisibleWithSubFocus", &AccessibilityUIElement::scrollToMakeVisibleWithSubFocusCallback); 455 bindMethod("scrollToGlobalPoint", &AccessibilityUIElement::scrollToGlobalPointCallback); 456 457 bindFallbackMethod(&AccessibilityUIElement::fallbackCallback); 458 } 459 460 AccessibilityUIElement* AccessibilityUIElement::getChildAtIndex(unsigned index) 461 { 462 return m_factory->getOrCreate(accessibilityObject().childAt(index)); 463 } 464 465 bool AccessibilityUIElement::isEqual(const WebKit::WebAccessibilityObject& other) 466 { 467 return accessibilityObject().equals(other); 468 } 469 470 void AccessibilityUIElement::notificationReceived(const char* notificationName) 471 { 472 size_t callbackCount = m_notificationCallbacks.size(); 473 for (size_t i = 0; i < callbackCount; i++) { 474 CppVariant notificationNameArgument; 475 notificationNameArgument.set(notificationName); 476 CppVariant invokeResult; 477 m_notificationCallbacks[i].invokeDefault(¬ificationNameArgument, 1, invokeResult); 478 } 479 } 480 481 // 482 // Properties 483 // 484 485 void AccessibilityUIElement::roleGetterCallback(CppVariant* result) 486 { 487 result->set(getRole(accessibilityObject())); 488 } 489 490 void AccessibilityUIElement::titleGetterCallback(CppVariant* result) 491 { 492 result->set(getTitle(accessibilityObject())); 493 } 494 495 void AccessibilityUIElement::descriptionGetterCallback(CppVariant* result) 496 { 497 result->set(getDescription(accessibilityObject())); 498 } 499 500 void AccessibilityUIElement::helpTextGetterCallback(CppVariant* result) 501 { 502 result->set(getHelpText(accessibilityObject())); 503 } 504 505 void AccessibilityUIElement::stringValueGetterCallback(CppVariant* result) 506 { 507 result->set(getStringValue(accessibilityObject())); 508 } 509 510 void AccessibilityUIElement::xGetterCallback(CppVariant* result) 511 { 512 result->set(accessibilityObject().boundingBoxRect().x); 513 } 514 515 void AccessibilityUIElement::yGetterCallback(CppVariant* result) 516 { 517 result->set(accessibilityObject().boundingBoxRect().y); 518 } 519 520 void AccessibilityUIElement::widthGetterCallback(CppVariant* result) 521 { 522 result->set(accessibilityObject().boundingBoxRect().width); 523 } 524 525 void AccessibilityUIElement::heightGetterCallback(CppVariant* result) 526 { 527 result->set(accessibilityObject().boundingBoxRect().height); 528 } 529 530 void AccessibilityUIElement::intValueGetterCallback(CppVariant* result) 531 { 532 if (accessibilityObject().supportsRangeValue()) 533 result->set(accessibilityObject().valueForRange()); 534 else if (accessibilityObject().roleValue() == WebAccessibilityRoleHeading) 535 result->set(accessibilityObject().headingLevel()); 536 else 537 result->set(atoi(accessibilityObject().stringValue().utf8().data())); 538 } 539 540 void AccessibilityUIElement::minValueGetterCallback(CppVariant* result) 541 { 542 result->set(accessibilityObject().minValueForRange()); 543 } 544 545 void AccessibilityUIElement::maxValueGetterCallback(CppVariant* result) 546 { 547 result->set(accessibilityObject().maxValueForRange()); 548 } 549 550 void AccessibilityUIElement::valueDescriptionGetterCallback(CppVariant* result) 551 { 552 result->set(getValueDescription(accessibilityObject())); 553 } 554 555 void AccessibilityUIElement::childrenCountGetterCallback(CppVariant* result) 556 { 557 int count = 1; // Root object always has only one child, the WebView. 558 if (!isRoot()) 559 count = accessibilityObject().childCount(); 560 result->set(count); 561 } 562 563 void AccessibilityUIElement::insertionPointLineNumberGetterCallback(CppVariant* result) 564 { 565 if (!accessibilityObject().isFocused()) { 566 result->set(-1); 567 return; 568 } 569 570 int lineNumber = accessibilityObject().selectionEndLineNumber(); 571 result->set(lineNumber); 572 } 573 574 void AccessibilityUIElement::selectedTextRangeGetterCallback(CppVariant* result) 575 { 576 unsigned selectionStart = accessibilityObject().selectionStart(); 577 unsigned selectionEnd = accessibilityObject().selectionEnd(); 578 char buffer[100]; 579 snprintf(buffer, sizeof(buffer), "{%d, %d}", selectionStart, selectionEnd - selectionStart); 580 581 result->set(std::string(buffer)); 582 } 583 584 void AccessibilityUIElement::isEnabledGetterCallback(CppVariant* result) 585 { 586 result->set(accessibilityObject().isEnabled()); 587 } 588 589 void AccessibilityUIElement::isRequiredGetterCallback(CppVariant* result) 590 { 591 result->set(accessibilityObject().isRequired()); 592 } 593 594 void AccessibilityUIElement::isFocusedGetterCallback(CppVariant* result) 595 { 596 result->set(accessibilityObject().isFocused()); 597 } 598 599 void AccessibilityUIElement::isFocusableGetterCallback(CppVariant* result) 600 { 601 result->set(accessibilityObject().canSetFocusAttribute()); 602 } 603 604 void AccessibilityUIElement::isSelectedGetterCallback(CppVariant* result) 605 { 606 result->set(accessibilityObject().isSelected()); 607 } 608 609 void AccessibilityUIElement::isSelectableGetterCallback(CppVariant* result) 610 { 611 result->set(accessibilityObject().canSetSelectedAttribute()); 612 } 613 614 void AccessibilityUIElement::isMultiSelectableGetterCallback(CppVariant* result) 615 { 616 result->set(accessibilityObject().isMultiSelectable()); 617 } 618 619 void AccessibilityUIElement::isSelectedOptionActiveGetterCallback(CppVariant* result) 620 { 621 result->set(accessibilityObject().isSelectedOptionActive()); 622 } 623 624 void AccessibilityUIElement::isExpandedGetterCallback(CppVariant* result) 625 { 626 result->set(!accessibilityObject().isCollapsed()); 627 } 628 629 void AccessibilityUIElement::isCheckedGetterCallback(CppVariant* result) 630 { 631 result->set(accessibilityObject().isChecked()); 632 } 633 634 void AccessibilityUIElement::isVisibleGetterCallback(CppVariant* result) 635 { 636 result->set(accessibilityObject().isVisible()); 637 } 638 639 void AccessibilityUIElement::isOffScreenGetterCallback(CppVariant* result) 640 { 641 result->set(accessibilityObject().isOffScreen()); 642 } 643 644 void AccessibilityUIElement::isCollapsedGetterCallback(CppVariant* result) 645 { 646 result->set(accessibilityObject().isCollapsed()); 647 } 648 649 void AccessibilityUIElement::hasPopupGetterCallback(CppVariant* result) 650 { 651 result->set(accessibilityObject().ariaHasPopup()); 652 } 653 654 void AccessibilityUIElement::isValidGetterCallback(CppVariant* result) 655 { 656 result->set(!accessibilityObject().isDetached()); 657 } 658 659 void AccessibilityUIElement::isReadOnlyGetterCallback(CppVariant* result) 660 { 661 result->set(accessibilityObject().isReadOnly()); 662 } 663 664 void AccessibilityUIElement::orientationGetterCallback(CppVariant* result) 665 { 666 result->set(getOrientation(accessibilityObject())); 667 } 668 669 void AccessibilityUIElement::clickPointXGetterCallback(CppVariant* result) 670 { 671 result->set(accessibilityObject().clickPoint().x); 672 } 673 674 void AccessibilityUIElement::clickPointYGetterCallback(CppVariant* result) 675 { 676 result->set(accessibilityObject().clickPoint().y); 677 } 678 679 void AccessibilityUIElement::rowCountGetterCallback(CppVariant* result) 680 { 681 result->set(static_cast<int32_t>(accessibilityObject().rowCount())); 682 } 683 684 void AccessibilityUIElement::columnCountGetterCallback(CppVariant* result) 685 { 686 result->set(static_cast<int32_t>(accessibilityObject().columnCount())); 687 } 688 689 // 690 // Methods 691 // 692 693 void AccessibilityUIElement::allAttributesCallback(const CppArgumentList&, CppVariant* result) 694 { 695 result->set(getAttributes(accessibilityObject())); 696 } 697 698 void AccessibilityUIElement::attributesOfLinkedUIElementsCallback(const CppArgumentList&, CppVariant* result) 699 { 700 result->setNull(); 701 } 702 703 void AccessibilityUIElement::attributesOfDocumentLinksCallback(const CppArgumentList&, CppVariant* result) 704 { 705 result->setNull(); 706 } 707 708 void AccessibilityUIElement::attributesOfChildrenCallback(const CppArgumentList& arguments, CppVariant* result) 709 { 710 AttributesCollector collector; 711 unsigned size = accessibilityObject().childCount(); 712 for (unsigned i = 0; i < size; ++i) 713 collector.collectAttributes(accessibilityObject().childAt(i)); 714 result->set(collector.attributes()); 715 } 716 717 void AccessibilityUIElement::parametrizedAttributeNamesCallback(const CppArgumentList&, CppVariant* result) 718 { 719 result->setNull(); 720 } 721 722 void AccessibilityUIElement::lineForIndexCallback(const CppArgumentList& arguments, CppVariant* result) 723 { 724 if (!arguments.size() || !arguments[0].isNumber()) { 725 result->setNull(); 726 return; 727 } 728 729 int index = arguments[0].toInt32(); 730 731 WebVector<int> lineBreaks; 732 accessibilityObject().lineBreaks(lineBreaks); 733 int line = 0; 734 int vectorSize = static_cast<int>(lineBreaks.size()); 735 while (line < vectorSize && lineBreaks[line] <= index) 736 line++; 737 result->set(line); 738 } 739 740 void AccessibilityUIElement::boundsForRangeCallback(const CppArgumentList&, CppVariant* result) 741 { 742 result->setNull(); 743 } 744 745 void AccessibilityUIElement::stringForRangeCallback(const CppArgumentList&, CppVariant* result) 746 { 747 result->setNull(); 748 } 749 750 void AccessibilityUIElement::childAtIndexCallback(const CppArgumentList& arguments, CppVariant* result) 751 { 752 if (!arguments.size() || !arguments[0].isNumber()) { 753 result->setNull(); 754 return; 755 } 756 757 AccessibilityUIElement* child = getChildAtIndex(arguments[0].toInt32()); 758 if (!child) { 759 result->setNull(); 760 return; 761 } 762 763 result->set(*(child->getAsCppVariant())); 764 } 765 766 void AccessibilityUIElement::elementAtPointCallback(const CppArgumentList& arguments, CppVariant* result) 767 { 768 result->setNull(); 769 770 if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isNumber()) 771 return; 772 773 int x = arguments[0].toInt32(); 774 int y = arguments[1].toInt32(); 775 WebPoint point(x, y); 776 WebAccessibilityObject obj = accessibilityObject().hitTest(point); 777 if (obj.isNull()) 778 return; 779 780 result->set(*(m_factory->getOrCreate(obj)->getAsCppVariant())); 781 } 782 783 void AccessibilityUIElement::attributesOfColumnHeadersCallback(const CppArgumentList&, CppVariant* result) 784 { 785 result->setNull(); 786 } 787 788 void AccessibilityUIElement::attributesOfRowHeadersCallback(const CppArgumentList&, CppVariant* result) 789 { 790 result->setNull(); 791 } 792 793 void AccessibilityUIElement::attributesOfColumnsCallback(const CppArgumentList&, CppVariant* result) 794 { 795 result->setNull(); 796 } 797 798 void AccessibilityUIElement::attributesOfRowsCallback(const CppArgumentList&, CppVariant* result) 799 { 800 result->setNull(); 801 } 802 803 void AccessibilityUIElement::attributesOfVisibleCellsCallback(const CppArgumentList&, CppVariant* result) 804 { 805 result->setNull(); 806 } 807 808 void AccessibilityUIElement::attributesOfHeaderCallback(const CppArgumentList&, CppVariant* result) 809 { 810 result->setNull(); 811 } 812 813 void AccessibilityUIElement::tableHeaderCallback(const CppArgumentList&, CppVariant* result) 814 { 815 WebAccessibilityObject obj = accessibilityObject().headerContainerObject(); 816 if (obj.isNull()) { 817 result->setNull(); 818 return; 819 } 820 821 result->set(*(m_factory->getOrCreate(obj)->getAsCppVariant())); 822 } 823 824 void AccessibilityUIElement::indexInTableCallback(const CppArgumentList&, CppVariant* result) 825 { 826 result->setNull(); 827 } 828 829 void AccessibilityUIElement::rowIndexRangeCallback(const CppArgumentList&, CppVariant* result) 830 { 831 unsigned rowIndex = accessibilityObject().cellRowIndex(); 832 unsigned rowSpan = accessibilityObject().cellRowSpan(); 833 char buffer[100]; 834 snprintf(buffer, sizeof(buffer), "{%d, %d}", rowIndex, rowSpan); 835 string value = buffer; 836 result->set(std::string(buffer)); 837 } 838 839 void AccessibilityUIElement::columnIndexRangeCallback(const CppArgumentList&, CppVariant* result) 840 { 841 unsigned columnIndex = accessibilityObject().cellColumnIndex(); 842 unsigned columnSpan = accessibilityObject().cellColumnSpan(); 843 char buffer[100]; 844 snprintf(buffer, sizeof(buffer), "{%d, %d}", columnIndex, columnSpan); 845 result->set(std::string(buffer)); 846 } 847 848 void AccessibilityUIElement::cellForColumnAndRowCallback(const CppArgumentList& arguments, CppVariant* result) 849 { 850 if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isNumber()) 851 return; 852 853 int column = arguments[0].toInt32(); 854 int row = arguments[1].toInt32(); 855 WebAccessibilityObject obj = accessibilityObject().cellForColumnAndRow(column, row); 856 if (obj.isNull()) { 857 result->setNull(); 858 return; 859 } 860 861 result->set(*(m_factory->getOrCreate(obj)->getAsCppVariant())); 862 } 863 864 void AccessibilityUIElement::titleUIElementCallback(const CppArgumentList&, CppVariant* result) 865 { 866 WebAccessibilityObject obj = accessibilityObject().titleUIElement(); 867 if (obj.isNull()) { 868 result->setNull(); 869 return; 870 } 871 872 result->set(*(m_factory->getOrCreate(obj)->getAsCppVariant())); 873 } 874 875 void AccessibilityUIElement::setSelectedTextRangeCallback(const CppArgumentList&arguments, CppVariant* result) 876 { 877 result->setNull(); 878 if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isNumber()) 879 return; 880 881 int selectionStart = arguments[0].toInt32(); 882 int selectionEnd = selectionStart + arguments[1].toInt32(); 883 accessibilityObject().setSelectedTextRange(selectionStart, selectionEnd); 884 } 885 886 void AccessibilityUIElement::attributeValueCallback(const CppArgumentList&, CppVariant* result) 887 { 888 result->setNull(); 889 } 890 891 void AccessibilityUIElement::isAttributeSettableCallback(const CppArgumentList& arguments, CppVariant* result) 892 { 893 if (arguments.size() < 1 && !arguments[0].isString()) { 894 result->setNull(); 895 return; 896 } 897 898 string attribute = arguments[0].toString(); 899 bool settable = false; 900 if (attribute == "AXValue") 901 settable = accessibilityObject().canSetValueAttribute(); 902 result->set(settable); 903 } 904 905 void AccessibilityUIElement::isPressActionSupportedCallback(const CppArgumentList&, CppVariant* result) 906 { 907 result->set(accessibilityObject().canPress()); 908 } 909 910 void AccessibilityUIElement::isIncrementActionSupportedCallback(const CppArgumentList&, CppVariant* result) 911 { 912 result->set(accessibilityObject().canIncrement()); 913 } 914 915 void AccessibilityUIElement::isDecrementActionSupportedCallback(const CppArgumentList&, CppVariant* result) 916 { 917 result->set(accessibilityObject().canDecrement()); 918 } 919 920 void AccessibilityUIElement::parentElementCallback(const CppArgumentList&, CppVariant* result) 921 { 922 AccessibilityUIElement* parent = m_factory->getOrCreate(accessibilityObject().parentObject()); 923 if (!parent) { 924 result->setNull(); 925 return; 926 } 927 928 result->set(*(parent->getAsCppVariant())); 929 } 930 931 void AccessibilityUIElement::incrementCallback(const CppArgumentList&, CppVariant* result) 932 { 933 accessibilityObject().increment(); 934 result->setNull(); 935 } 936 937 void AccessibilityUIElement::decrementCallback(const CppArgumentList&, CppVariant* result) 938 { 939 accessibilityObject().decrement(); 940 result->setNull(); 941 } 942 943 void AccessibilityUIElement::showMenuCallback(const CppArgumentList&, CppVariant* result) 944 { 945 result->setNull(); 946 } 947 948 void AccessibilityUIElement::pressCallback(const CppArgumentList&, CppVariant* result) 949 { 950 accessibilityObject().press(); 951 result->setNull(); 952 } 953 954 void AccessibilityUIElement::isEqualCallback(const CppArgumentList& arguments, CppVariant* result) 955 { 956 if (arguments.size() < 1 || !arguments[0].isObject()) { 957 result->setNull(); 958 return; 959 } 960 961 result->set(arguments[0].isEqual(*getAsCppVariant())); 962 } 963 964 void AccessibilityUIElement::addNotificationListenerCallback(const CppArgumentList& arguments, CppVariant* result) 965 { 966 if (arguments.size() < 1 || !arguments[0].isObject()) { 967 result->setNull(); 968 return; 969 } 970 971 m_notificationCallbacks.push_back(arguments[0]); 972 result->setNull(); 973 } 974 975 void AccessibilityUIElement::removeNotificationListenerCallback(const CppArgumentList&, CppVariant* result) 976 { 977 // FIXME: Implement this. 978 result->setNull(); 979 } 980 981 void AccessibilityUIElement::takeFocusCallback(const CppArgumentList&, CppVariant* result) 982 { 983 accessibilityObject().setFocused(true); 984 result->setNull(); 985 } 986 987 void AccessibilityUIElement::scrollToMakeVisibleCallback(const CppArgumentList&, CppVariant* result) 988 { 989 accessibilityObject().scrollToMakeVisible(); 990 result->setNull(); 991 } 992 993 void AccessibilityUIElement::scrollToMakeVisibleWithSubFocusCallback(const CppArgumentList& arguments, CppVariant* result) 994 { 995 result->setNull(); 996 997 if (arguments.size() != 4 998 || !arguments[0].isNumber() 999 || !arguments[1].isNumber() 1000 || !arguments[2].isNumber() 1001 || !arguments[3].isNumber()) 1002 return; 1003 1004 int x = arguments[0].toInt32(); 1005 int y = arguments[1].toInt32(); 1006 int width = arguments[2].toInt32(); 1007 int height = arguments[3].toInt32(); 1008 accessibilityObject().scrollToMakeVisibleWithSubFocus(WebRect(x, y, width, height)); 1009 result->setNull(); 1010 } 1011 1012 void AccessibilityUIElement::scrollToGlobalPointCallback(const CppArgumentList& arguments, CppVariant* result) 1013 { 1014 result->setNull(); 1015 1016 if (arguments.size() != 2 1017 || !arguments[0].isNumber() 1018 || !arguments[1].isNumber()) 1019 return; 1020 1021 int x = arguments[0].toInt32(); 1022 int y = arguments[1].toInt32(); 1023 1024 accessibilityObject().scrollToGlobalPoint(WebPoint(x, y)); 1025 result->setNull(); 1026 } 1027 1028 void AccessibilityUIElement::fallbackCallback(const CppArgumentList &, CppVariant* result) 1029 { 1030 // FIXME: Implement this. 1031 result->setNull(); 1032 } 1033 1034 RootAccessibilityUIElement::RootAccessibilityUIElement(const WebAccessibilityObject &object, Factory *factory) 1035 : AccessibilityUIElement(object, factory) { } 1036 1037 AccessibilityUIElement* RootAccessibilityUIElement::getChildAtIndex(unsigned index) 1038 { 1039 if (index) 1040 return 0; 1041 1042 return factory()->getOrCreate(accessibilityObject()); 1043 } 1044 1045 1046 AccessibilityUIElementList ::~AccessibilityUIElementList() 1047 { 1048 clear(); 1049 } 1050 1051 void AccessibilityUIElementList::clear() 1052 { 1053 for (ElementList::iterator i = m_elements.begin(); i != m_elements.end(); ++i) 1054 delete (*i); 1055 m_elements.clear(); 1056 } 1057 1058 AccessibilityUIElement* AccessibilityUIElementList::getOrCreate(const WebAccessibilityObject& object) 1059 { 1060 if (object.isNull()) 1061 return 0; 1062 1063 size_t elementCount = m_elements.size(); 1064 for (size_t i = 0; i < elementCount; i++) { 1065 if (m_elements[i]->isEqual(object)) 1066 return m_elements[i]; 1067 } 1068 1069 AccessibilityUIElement* element = new AccessibilityUIElement(object, this); 1070 m_elements.push_back(element); 1071 return element; 1072 } 1073 1074 AccessibilityUIElement* AccessibilityUIElementList::createRoot(const WebAccessibilityObject& object) 1075 { 1076 AccessibilityUIElement* element = new RootAccessibilityUIElement(object, this); 1077 m_elements.push_back(element); 1078 return element; 1079 } 1080 1081 } 1082