| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "webkit/glue/webaccessibility.h" | |
| 6 | |
| 7 #include <set> | |
| 8 | |
| 9 #include "base/string_number_conversions.h" | |
| 10 #include "base/string_util.h" | |
| 11 #include "base/utf_string_conversions.h" | |
| 12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityObjec
t.h" | |
| 13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityRole.
h" | |
| 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | |
| 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocumentType.h" | |
| 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" | |
| 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement
.h" | |
| 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | |
| 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h" | |
| 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" | |
| 21 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h" | |
| 22 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h" | |
| 23 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" | |
| 24 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h" | |
| 25 | |
| 26 using base::DoubleToString; | |
| 27 using base::IntToString; | |
| 28 using WebKit::WebAccessibilityRole; | |
| 29 using WebKit::WebAccessibilityObject; | |
| 30 | |
| 31 namespace { | |
| 32 | |
| 33 std::string IntVectorToString(const std::vector<int>& items) { | |
| 34 std::string str; | |
| 35 for (size_t i = 0; i < items.size(); ++i) { | |
| 36 if (i > 0) | |
| 37 str += ","; | |
| 38 str += IntToString(items[i]); | |
| 39 } | |
| 40 return str; | |
| 41 } | |
| 42 | |
| 43 } // Anonymous namespace | |
| 44 | |
| 45 namespace webkit_glue { | |
| 46 | |
| 47 // Provides a conversion between the WebKit::WebAccessibilityRole and a role | |
| 48 // supported on the Browser side. Listed alphabetically by the | |
| 49 // WebAccessibilityRole (except for default role). | |
| 50 WebAccessibility::Role ConvertRole(WebKit::WebAccessibilityRole role) { | |
| 51 switch (role) { | |
| 52 case WebKit::WebAccessibilityRoleAnnotation: | |
| 53 return WebAccessibility::ROLE_ANNOTATION; | |
| 54 case WebKit::WebAccessibilityRoleApplication: | |
| 55 return WebAccessibility::ROLE_APPLICATION; | |
| 56 case WebKit::WebAccessibilityRoleApplicationAlert: | |
| 57 return WebAccessibility::ROLE_ALERT; | |
| 58 case WebKit::WebAccessibilityRoleApplicationAlertDialog: | |
| 59 return WebAccessibility::ROLE_ALERT_DIALOG; | |
| 60 case WebKit::WebAccessibilityRoleApplicationDialog: | |
| 61 return WebAccessibility::ROLE_DIALOG; | |
| 62 case WebKit::WebAccessibilityRoleApplicationLog: | |
| 63 return WebAccessibility::ROLE_LOG; | |
| 64 case WebKit::WebAccessibilityRoleApplicationMarquee: | |
| 65 return WebAccessibility::ROLE_MARQUEE; | |
| 66 case WebKit::WebAccessibilityRoleApplicationStatus: | |
| 67 return WebAccessibility::ROLE_STATUS; | |
| 68 case WebKit::WebAccessibilityRoleApplicationTimer: | |
| 69 return WebAccessibility::ROLE_TIMER; | |
| 70 case WebKit::WebAccessibilityRoleBrowser: | |
| 71 return WebAccessibility::ROLE_BROWSER; | |
| 72 case WebKit::WebAccessibilityRoleBusyIndicator: | |
| 73 return WebAccessibility::ROLE_BUSY_INDICATOR; | |
| 74 case WebKit::WebAccessibilityRoleButton: | |
| 75 return WebAccessibility::ROLE_BUTTON; | |
| 76 case WebKit::WebAccessibilityRoleCell: | |
| 77 return WebAccessibility::ROLE_CELL; | |
| 78 case WebKit::WebAccessibilityRoleCheckBox: | |
| 79 return WebAccessibility::ROLE_CHECKBOX; | |
| 80 case WebKit::WebAccessibilityRoleColorWell: | |
| 81 return WebAccessibility::ROLE_COLOR_WELL; | |
| 82 case WebKit::WebAccessibilityRoleColumn: | |
| 83 return WebAccessibility::ROLE_COLUMN; | |
| 84 case WebKit::WebAccessibilityRoleColumnHeader: | |
| 85 return WebAccessibility::ROLE_COLUMN_HEADER; | |
| 86 case WebKit::WebAccessibilityRoleComboBox: | |
| 87 return WebAccessibility::ROLE_COMBO_BOX; | |
| 88 case WebKit::WebAccessibilityRoleDefinitionListDefinition: | |
| 89 return WebAccessibility::ROLE_DEFINITION_LIST_DEFINITION; | |
| 90 case WebKit::WebAccessibilityRoleDefinitionListTerm: | |
| 91 return WebAccessibility::ROLE_DEFINITION_LIST_TERM; | |
| 92 case WebKit::WebAccessibilityRoleDirectory: | |
| 93 return WebAccessibility::ROLE_DIRECTORY; | |
| 94 case WebKit::WebAccessibilityRoleDisclosureTriangle: | |
| 95 return WebAccessibility::ROLE_DISCLOSURE_TRIANGLE; | |
| 96 case WebKit::WebAccessibilityRoleDocument: | |
| 97 return WebAccessibility::ROLE_DOCUMENT; | |
| 98 case WebKit::WebAccessibilityRoleDocumentArticle: | |
| 99 return WebAccessibility::ROLE_ARTICLE; | |
| 100 case WebKit::WebAccessibilityRoleDocumentMath: | |
| 101 return WebAccessibility::ROLE_MATH; | |
| 102 case WebKit::WebAccessibilityRoleDocumentNote: | |
| 103 return WebAccessibility::ROLE_NOTE; | |
| 104 case WebKit::WebAccessibilityRoleDocumentRegion: | |
| 105 return WebAccessibility::ROLE_REGION; | |
| 106 case WebKit::WebAccessibilityRoleDrawer: | |
| 107 return WebAccessibility::ROLE_DRAWER; | |
| 108 case WebKit::WebAccessibilityRoleEditableText: | |
| 109 return WebAccessibility::ROLE_EDITABLE_TEXT; | |
| 110 case WebKit::WebAccessibilityRoleFooter: | |
| 111 return WebAccessibility::ROLE_FOOTER; | |
| 112 case WebKit::WebAccessibilityRoleGrid: | |
| 113 return WebAccessibility::ROLE_GRID; | |
| 114 case WebKit::WebAccessibilityRoleGroup: | |
| 115 return WebAccessibility::ROLE_GROUP; | |
| 116 case WebKit::WebAccessibilityRoleGrowArea: | |
| 117 return WebAccessibility::ROLE_GROW_AREA; | |
| 118 case WebKit::WebAccessibilityRoleHeading: | |
| 119 return WebAccessibility::ROLE_HEADING; | |
| 120 case WebKit::WebAccessibilityRoleHelpTag: | |
| 121 return WebAccessibility::ROLE_HELP_TAG; | |
| 122 case WebKit::WebAccessibilityRoleIgnored: | |
| 123 return WebAccessibility::ROLE_IGNORED; | |
| 124 case WebKit::WebAccessibilityRoleImage: | |
| 125 return WebAccessibility::ROLE_IMAGE; | |
| 126 case WebKit::WebAccessibilityRoleImageMap: | |
| 127 return WebAccessibility::ROLE_IMAGE_MAP; | |
| 128 case WebKit::WebAccessibilityRoleImageMapLink: | |
| 129 return WebAccessibility::ROLE_IMAGE_MAP_LINK; | |
| 130 case WebKit::WebAccessibilityRoleIncrementor: | |
| 131 return WebAccessibility::ROLE_INCREMENTOR; | |
| 132 case WebKit::WebAccessibilityRoleLandmarkApplication: | |
| 133 return WebAccessibility::ROLE_LANDMARK_APPLICATION; | |
| 134 case WebKit::WebAccessibilityRoleLandmarkBanner: | |
| 135 return WebAccessibility::ROLE_LANDMARK_BANNER; | |
| 136 case WebKit::WebAccessibilityRoleLandmarkComplementary: | |
| 137 return WebAccessibility::ROLE_LANDMARK_COMPLEMENTARY; | |
| 138 case WebKit::WebAccessibilityRoleLandmarkContentInfo: | |
| 139 return WebAccessibility::ROLE_LANDMARK_CONTENTINFO; | |
| 140 case WebKit::WebAccessibilityRoleLandmarkMain: | |
| 141 return WebAccessibility::ROLE_LANDMARK_MAIN; | |
| 142 case WebKit::WebAccessibilityRoleLandmarkNavigation: | |
| 143 return WebAccessibility::ROLE_LANDMARK_NAVIGATION; | |
| 144 case WebKit::WebAccessibilityRoleLandmarkSearch: | |
| 145 return WebAccessibility::ROLE_LANDMARK_SEARCH; | |
| 146 case WebKit::WebAccessibilityRoleLink: | |
| 147 return WebAccessibility::ROLE_LINK; | |
| 148 case WebKit::WebAccessibilityRoleList: | |
| 149 return WebAccessibility::ROLE_LIST; | |
| 150 case WebKit::WebAccessibilityRoleListBox: | |
| 151 return WebAccessibility::ROLE_LISTBOX; | |
| 152 case WebKit::WebAccessibilityRoleListBoxOption: | |
| 153 return WebAccessibility::ROLE_LISTBOX_OPTION; | |
| 154 case WebKit::WebAccessibilityRoleListItem: | |
| 155 return WebAccessibility::ROLE_LIST_ITEM; | |
| 156 case WebKit::WebAccessibilityRoleListMarker: | |
| 157 return WebAccessibility::ROLE_LIST_MARKER; | |
| 158 case WebKit::WebAccessibilityRoleMatte: | |
| 159 return WebAccessibility::ROLE_MATTE; | |
| 160 case WebKit::WebAccessibilityRoleMenu: | |
| 161 return WebAccessibility::ROLE_MENU; | |
| 162 case WebKit::WebAccessibilityRoleMenuBar: | |
| 163 return WebAccessibility::ROLE_MENU_BAR; | |
| 164 case WebKit::WebAccessibilityRoleMenuButton: | |
| 165 return WebAccessibility::ROLE_MENU_BUTTON; | |
| 166 case WebKit::WebAccessibilityRoleMenuItem: | |
| 167 return WebAccessibility::ROLE_MENU_ITEM; | |
| 168 case WebKit::WebAccessibilityRoleMenuListOption: | |
| 169 return WebAccessibility::ROLE_MENU_LIST_OPTION; | |
| 170 case WebKit::WebAccessibilityRoleMenuListPopup: | |
| 171 return WebAccessibility::ROLE_MENU_LIST_POPUP; | |
| 172 case WebKit::WebAccessibilityRoleOutline: | |
| 173 return WebAccessibility::ROLE_OUTLINE; | |
| 174 case WebKit::WebAccessibilityRolePopUpButton: | |
| 175 return WebAccessibility::ROLE_POPUP_BUTTON; | |
| 176 case WebKit::WebAccessibilityRoleProgressIndicator: | |
| 177 return WebAccessibility::ROLE_PROGRESS_INDICATOR; | |
| 178 case WebKit::WebAccessibilityRoleRadioButton: | |
| 179 return WebAccessibility::ROLE_RADIO_BUTTON; | |
| 180 case WebKit::WebAccessibilityRoleRadioGroup: | |
| 181 return WebAccessibility::ROLE_RADIO_GROUP; | |
| 182 case WebKit::WebAccessibilityRoleRow: | |
| 183 return WebAccessibility::ROLE_ROW; | |
| 184 case WebKit::WebAccessibilityRoleRowHeader: | |
| 185 return WebAccessibility::ROLE_ROW_HEADER; | |
| 186 case WebKit::WebAccessibilityRoleRuler: | |
| 187 return WebAccessibility::ROLE_RULER; | |
| 188 case WebKit::WebAccessibilityRoleRulerMarker: | |
| 189 return WebAccessibility::ROLE_RULER_MARKER; | |
| 190 case WebKit::WebAccessibilityRoleScrollArea: | |
| 191 return WebAccessibility::ROLE_SCROLLAREA; | |
| 192 case WebKit::WebAccessibilityRoleScrollBar: | |
| 193 return WebAccessibility::ROLE_SCROLLBAR; | |
| 194 case WebKit::WebAccessibilityRoleSheet: | |
| 195 return WebAccessibility::ROLE_SHEET; | |
| 196 case WebKit::WebAccessibilityRoleSlider: | |
| 197 return WebAccessibility::ROLE_SLIDER; | |
| 198 case WebKit::WebAccessibilityRoleSliderThumb: | |
| 199 return WebAccessibility::ROLE_SLIDER_THUMB; | |
| 200 case WebKit::WebAccessibilityRoleSplitGroup: | |
| 201 return WebAccessibility::ROLE_SPLIT_GROUP; | |
| 202 case WebKit::WebAccessibilityRoleSplitter: | |
| 203 return WebAccessibility::ROLE_SPLITTER; | |
| 204 case WebKit::WebAccessibilityRoleStaticText: | |
| 205 return WebAccessibility::ROLE_STATIC_TEXT; | |
| 206 case WebKit::WebAccessibilityRoleSystemWide: | |
| 207 return WebAccessibility::ROLE_SYSTEM_WIDE; | |
| 208 case WebKit::WebAccessibilityRoleTab: | |
| 209 return WebAccessibility::ROLE_TAB; | |
| 210 case WebKit::WebAccessibilityRoleTabGroup: | |
| 211 return WebAccessibility::ROLE_TAB_GROUP_UNUSED; | |
| 212 case WebKit::WebAccessibilityRoleTabList: | |
| 213 return WebAccessibility::ROLE_TAB_LIST; | |
| 214 case WebKit::WebAccessibilityRoleTabPanel: | |
| 215 return WebAccessibility::ROLE_TAB_PANEL; | |
| 216 case WebKit::WebAccessibilityRoleTable: | |
| 217 return WebAccessibility::ROLE_TABLE; | |
| 218 case WebKit::WebAccessibilityRoleTableHeaderContainer: | |
| 219 return WebAccessibility::ROLE_TABLE_HEADER_CONTAINER; | |
| 220 case WebKit::WebAccessibilityRoleTextArea: | |
| 221 return WebAccessibility::ROLE_TEXTAREA; | |
| 222 case WebKit::WebAccessibilityRoleTextField: | |
| 223 return WebAccessibility::ROLE_TEXT_FIELD; | |
| 224 case WebKit::WebAccessibilityRoleToolbar: | |
| 225 return WebAccessibility::ROLE_TOOLBAR; | |
| 226 case WebKit::WebAccessibilityRoleTreeGrid: | |
| 227 return WebAccessibility::ROLE_TREE_GRID; | |
| 228 case WebKit::WebAccessibilityRoleTreeItemRole: | |
| 229 return WebAccessibility::ROLE_TREE_ITEM; | |
| 230 case WebKit::WebAccessibilityRoleTreeRole: | |
| 231 return WebAccessibility::ROLE_TREE; | |
| 232 case WebKit::WebAccessibilityRoleUserInterfaceTooltip: | |
| 233 return WebAccessibility::ROLE_TOOLTIP; | |
| 234 case WebKit::WebAccessibilityRoleValueIndicator: | |
| 235 return WebAccessibility::ROLE_VALUE_INDICATOR; | |
| 236 case WebKit::WebAccessibilityRoleWebArea: | |
| 237 return WebAccessibility::ROLE_WEB_AREA; | |
| 238 case WebKit::WebAccessibilityRoleWebCoreLink: | |
| 239 return WebAccessibility::ROLE_WEBCORE_LINK; | |
| 240 case WebKit::WebAccessibilityRoleWindow: | |
| 241 return WebAccessibility::ROLE_WINDOW; | |
| 242 | |
| 243 default: | |
| 244 return WebAccessibility::ROLE_UNKNOWN; | |
| 245 } | |
| 246 } | |
| 247 | |
| 248 uint32 ConvertState(const WebAccessibilityObject& o) { | |
| 249 uint32 state = 0; | |
| 250 if (o.isChecked()) | |
| 251 state |= (1 << WebAccessibility::STATE_CHECKED); | |
| 252 | |
| 253 if (o.isCollapsed()) | |
| 254 state |= (1 << WebAccessibility::STATE_COLLAPSED); | |
| 255 | |
| 256 if (o.canSetFocusAttribute()) | |
| 257 state |= (1 << WebAccessibility::STATE_FOCUSABLE); | |
| 258 | |
| 259 if (o.isFocused()) | |
| 260 state |= (1 << WebAccessibility::STATE_FOCUSED); | |
| 261 | |
| 262 if (o.roleValue() == WebKit::WebAccessibilityRolePopUpButton || | |
| 263 o.ariaHasPopup()) { | |
| 264 state |= (1 << WebAccessibility::STATE_HASPOPUP); | |
| 265 if (!o.isCollapsed()) | |
| 266 state |= (1 << WebAccessibility::STATE_EXPANDED); | |
| 267 } | |
| 268 | |
| 269 if (o.isHovered()) | |
| 270 state |= (1 << WebAccessibility::STATE_HOTTRACKED); | |
| 271 | |
| 272 if (o.isIndeterminate()) | |
| 273 state |= (1 << WebAccessibility::STATE_INDETERMINATE); | |
| 274 | |
| 275 if (!o.isVisible()) | |
| 276 state |= (1 << WebAccessibility::STATE_INVISIBLE); | |
| 277 | |
| 278 if (o.isLinked()) | |
| 279 state |= (1 << WebAccessibility::STATE_LINKED); | |
| 280 | |
| 281 if (o.isMultiSelectable()) | |
| 282 state |= (1 << WebAccessibility::STATE_MULTISELECTABLE); | |
| 283 | |
| 284 if (o.isOffScreen()) | |
| 285 state |= (1 << WebAccessibility::STATE_OFFSCREEN); | |
| 286 | |
| 287 if (o.isPressed()) | |
| 288 state |= (1 << WebAccessibility::STATE_PRESSED); | |
| 289 | |
| 290 if (o.isPasswordField()) | |
| 291 state |= (1 << WebAccessibility::STATE_PROTECTED); | |
| 292 | |
| 293 if (o.isReadOnly()) | |
| 294 state |= (1 << WebAccessibility::STATE_READONLY); | |
| 295 | |
| 296 if (o.isRequired()) | |
| 297 state |= (1 << WebAccessibility::STATE_REQUIRED); | |
| 298 | |
| 299 if (o.canSetSelectedAttribute()) | |
| 300 state |= (1 << WebAccessibility::STATE_SELECTABLE); | |
| 301 | |
| 302 if (o.isSelected()) | |
| 303 state |= (1 << WebAccessibility::STATE_SELECTED); | |
| 304 | |
| 305 if (o.isVisited()) | |
| 306 state |= (1 << WebAccessibility::STATE_TRAVERSED); | |
| 307 | |
| 308 if (!o.isEnabled()) | |
| 309 state |= (1 << WebAccessibility::STATE_UNAVAILABLE); | |
| 310 | |
| 311 if (o.isVertical()) | |
| 312 state |= (1 << WebAccessibility::STATE_VERTICAL); | |
| 313 | |
| 314 if (o.isVisited()) | |
| 315 state |= (1 << WebAccessibility::STATE_VISITED); | |
| 316 | |
| 317 return state; | |
| 318 } | |
| 319 | |
| 320 WebAccessibility::WebAccessibility() | |
| 321 : id(-1), | |
| 322 role(ROLE_UNKNOWN), | |
| 323 state(-1) { | |
| 324 } | |
| 325 | |
| 326 WebAccessibility::WebAccessibility(const WebKit::WebAccessibilityObject& src, | |
| 327 IncludeChildren include_children, | |
| 328 IncludeLineBreaks include_line_breaks) { | |
| 329 Init(src, include_children, include_line_breaks); | |
| 330 } | |
| 331 | |
| 332 WebAccessibility::~WebAccessibility() { | |
| 333 } | |
| 334 | |
| 335 #ifndef NDEBUG | |
| 336 std::string WebAccessibility::DebugString(bool recursive) const { | |
| 337 std::string result; | |
| 338 static int indent = 0; | |
| 339 result += "\n"; | |
| 340 for (int i = 0; i < indent; ++i) | |
| 341 result += " "; | |
| 342 | |
| 343 result += "id=" + IntToString(id); | |
| 344 | |
| 345 switch (role) { | |
| 346 case ROLE_ALERT: result += " ALERT"; break; | |
| 347 case ROLE_ALERT_DIALOG: result += " ALERT_DIALOG"; break; | |
| 348 case ROLE_ANNOTATION: result += " ANNOTATION"; break; | |
| 349 case ROLE_APPLICATION: result += " APPLICATION"; break; | |
| 350 case ROLE_ARTICLE: result += " ARTICLE"; break; | |
| 351 case ROLE_BROWSER: result += " BROWSER"; break; | |
| 352 case ROLE_BUSY_INDICATOR: result += " BUSY_INDICATOR"; break; | |
| 353 case ROLE_BUTTON: result += " BUTTON"; break; | |
| 354 case ROLE_CELL: result += " CELL"; break; | |
| 355 case ROLE_CHECKBOX: result += " CHECKBOX"; break; | |
| 356 case ROLE_COLOR_WELL: result += " COLOR_WELL"; break; | |
| 357 case ROLE_COLUMN: result += " COLUMN"; break; | |
| 358 case ROLE_COLUMN_HEADER: result += " COLUMN_HEADER"; break; | |
| 359 case ROLE_COMBO_BOX: result += " COMBO_BOX"; break; | |
| 360 case ROLE_DEFINITION_LIST_DEFINITION: result += " DL_DEFINITION"; break; | |
| 361 case ROLE_DEFINITION_LIST_TERM: result += " DL_TERM"; break; | |
| 362 case ROLE_DIALOG: result += " DIALOG"; break; | |
| 363 case ROLE_DIRECTORY: result += " DIRECTORY"; break; | |
| 364 case ROLE_DISCLOSURE_TRIANGLE: result += " DISCLOSURE_TRIANGLE"; break; | |
| 365 case ROLE_DOCUMENT: result += " DOCUMENT"; break; | |
| 366 case ROLE_DRAWER: result += " DRAWER"; break; | |
| 367 case ROLE_EDITABLE_TEXT: result += " EDITABLE_TEXT"; break; | |
| 368 case ROLE_GRID: result += " GRID"; break; | |
| 369 case ROLE_GROUP: result += " GROUP"; break; | |
| 370 case ROLE_GROW_AREA: result += " GROW_AREA"; break; | |
| 371 case ROLE_HEADING: result += " HEADING"; break; | |
| 372 case ROLE_HELP_TAG: result += " HELP_TAG"; break; | |
| 373 case ROLE_IGNORED: result += " IGNORED"; break; | |
| 374 case ROLE_IMAGE: result += " IMAGE"; break; | |
| 375 case ROLE_IMAGE_MAP: result += " IMAGE_MAP"; break; | |
| 376 case ROLE_IMAGE_MAP_LINK: result += " IMAGE_MAP_LINK"; break; | |
| 377 case ROLE_INCREMENTOR: result += " INCREMENTOR"; break; | |
| 378 case ROLE_LANDMARK_APPLICATION: result += " L_APPLICATION"; break; | |
| 379 case ROLE_LANDMARK_BANNER: result += " L_BANNER"; break; | |
| 380 case ROLE_LANDMARK_COMPLEMENTARY: result += " L_COMPLEMENTARY"; break; | |
| 381 case ROLE_LANDMARK_CONTENTINFO: result += " L_CONTENTINFO"; break; | |
| 382 case ROLE_LANDMARK_MAIN: result += " L_MAIN"; break; | |
| 383 case ROLE_LANDMARK_NAVIGATION: result += " L_NAVIGATION"; break; | |
| 384 case ROLE_LANDMARK_SEARCH: result += " L_SEARCH"; break; | |
| 385 case ROLE_LINK: result += " LINK"; break; | |
| 386 case ROLE_LIST: result += " LIST"; break; | |
| 387 case ROLE_LISTBOX: result += " LISTBOX"; break; | |
| 388 case ROLE_LISTBOX_OPTION: result += " LISTBOX_OPTION"; break; | |
| 389 case ROLE_LIST_ITEM: result += " LIST_ITEM"; break; | |
| 390 case ROLE_LIST_MARKER: result += " LIST_MARKER"; break; | |
| 391 case ROLE_LOG: result += " LOG"; break; | |
| 392 case ROLE_MARQUEE: result += " MARQUEE"; break; | |
| 393 case ROLE_MATH: result += " MATH"; break; | |
| 394 case ROLE_MATTE: result += " MATTE"; break; | |
| 395 case ROLE_MENU: result += " MENU"; break; | |
| 396 case ROLE_MENU_BAR: result += " MENU_BAR"; break; | |
| 397 case ROLE_MENU_BUTTON: result += " MENU_BUTTON"; break; | |
| 398 case ROLE_MENU_ITEM: result += " MENU_ITEM"; break; | |
| 399 case ROLE_MENU_LIST_OPTION: result += " MENU_LIST_OPTION"; break; | |
| 400 case ROLE_MENU_LIST_POPUP: result += " MENU_LIST_POPUP"; break; | |
| 401 case ROLE_NOTE: result += " NOTE"; break; | |
| 402 case ROLE_OUTLINE: result += " OUTLINE"; break; | |
| 403 case ROLE_POPUP_BUTTON: result += " POPUP_BUTTON"; break; | |
| 404 case ROLE_PROGRESS_INDICATOR: result += " PROGRESS_INDICATOR"; break; | |
| 405 case ROLE_RADIO_BUTTON: result += " RADIO_BUTTON"; break; | |
| 406 case ROLE_RADIO_GROUP: result += " RADIO_GROUP"; break; | |
| 407 case ROLE_REGION: result += " REGION"; break; | |
| 408 case ROLE_ROOT_WEB_AREA: result += " ROOT_WEB_AREA"; break; | |
| 409 case ROLE_ROW: result += " ROW"; break; | |
| 410 case ROLE_ROW_HEADER: result += " ROW_HEADER"; break; | |
| 411 case ROLE_RULER: result += " RULER"; break; | |
| 412 case ROLE_RULER_MARKER: result += " RULER_MARKER"; break; | |
| 413 case ROLE_SCROLLAREA: result += " SCROLLAREA"; break; | |
| 414 case ROLE_SCROLLBAR: result += " SCROLLBAR"; break; | |
| 415 case ROLE_SHEET: result += " SHEET"; break; | |
| 416 case ROLE_SLIDER: result += " SLIDER"; break; | |
| 417 case ROLE_SLIDER_THUMB: result += " SLIDER_THUMB"; break; | |
| 418 case ROLE_SPLITTER: result += " SPLITTER"; break; | |
| 419 case ROLE_SPLIT_GROUP: result += " SPLIT_GROUP"; break; | |
| 420 case ROLE_STATIC_TEXT: result += " STATIC_TEXT"; break; | |
| 421 case ROLE_STATUS: result += " STATUS"; break; | |
| 422 case ROLE_SYSTEM_WIDE: result += " SYSTEM_WIDE"; break; | |
| 423 case ROLE_TAB: result += " TAB"; break; | |
| 424 case ROLE_TABLE: result += " TABLE"; break; | |
| 425 case ROLE_TABLE_HEADER_CONTAINER: result += " TABLE_HDR_CONTAINER"; break; | |
| 426 case ROLE_TAB_GROUP_UNUSED: result += " TAB_GROUP_UNUSED"; break; | |
| 427 case ROLE_TAB_LIST: result += " TAB_LIST"; break; | |
| 428 case ROLE_TAB_PANEL: result += " TAB_PANEL"; break; | |
| 429 case ROLE_TEXTAREA: result += " TEXTAREA"; break; | |
| 430 case ROLE_TEXT_FIELD: result += " TEXT_FIELD"; break; | |
| 431 case ROLE_TIMER: result += " TIMER"; break; | |
| 432 case ROLE_TOOLBAR: result += " TOOLBAR"; break; | |
| 433 case ROLE_TOOLTIP: result += " TOOLTIP"; break; | |
| 434 case ROLE_TREE: result += " TREE"; break; | |
| 435 case ROLE_TREE_GRID: result += " TREE_GRID"; break; | |
| 436 case ROLE_TREE_ITEM: result += " TREE_ITEM"; break; | |
| 437 case ROLE_UNKNOWN: result += " UNKNOWN"; break; | |
| 438 case ROLE_VALUE_INDICATOR: result += " VALUE_INDICATOR"; break; | |
| 439 case ROLE_WEBCORE_LINK: result += " WEBCORE_LINK"; break; | |
| 440 case ROLE_WEB_AREA: result += " WEB_AREA"; break; | |
| 441 case ROLE_WINDOW: result += " WINDOW"; break; | |
| 442 default: | |
| 443 assert(false); | |
| 444 } | |
| 445 | |
| 446 if (state & (1 << STATE_BUSY)) | |
| 447 result += " BUSY"; | |
| 448 if (state & (1 << STATE_CHECKED)) | |
| 449 result += " CHECKED"; | |
| 450 if (state & (1 << STATE_COLLAPSED)) | |
| 451 result += " COLLAPSED"; | |
| 452 if (state & (1 << STATE_EXPANDED)) | |
| 453 result += " EXPANDED"; | |
| 454 if (state & (1 << STATE_FOCUSABLE)) | |
| 455 result += " FOCUSABLE"; | |
| 456 if (state & (1 << STATE_FOCUSED)) | |
| 457 result += " FOCUSED"; | |
| 458 if (state & (1 << STATE_HASPOPUP)) | |
| 459 result += " HASPOPUP"; | |
| 460 if (state & (1 << STATE_HOTTRACKED)) | |
| 461 result += " HOTTRACKED"; | |
| 462 if (state & (1 << STATE_INDETERMINATE)) | |
| 463 result += " INDETERMINATE"; | |
| 464 if (state & (1 << STATE_INVISIBLE)) | |
| 465 result += " INVISIBLE"; | |
| 466 if (state & (1 << STATE_LINKED)) | |
| 467 result += " LINKED"; | |
| 468 if (state & (1 << STATE_MULTISELECTABLE)) | |
| 469 result += " MULTISELECTABLE"; | |
| 470 if (state & (1 << STATE_OFFSCREEN)) | |
| 471 result += " OFFSCREEN"; | |
| 472 if (state & (1 << STATE_PRESSED)) | |
| 473 result += " PRESSED"; | |
| 474 if (state & (1 << STATE_PROTECTED)) | |
| 475 result += " PROTECTED"; | |
| 476 if (state & (1 << STATE_READONLY)) | |
| 477 result += " READONLY"; | |
| 478 if (state & (1 << STATE_REQUIRED)) | |
| 479 result += " REQUIRED"; | |
| 480 if (state & (1 << STATE_SELECTABLE)) | |
| 481 result += " SELECTABLE"; | |
| 482 if (state & (1 << STATE_SELECTED)) | |
| 483 result += " SELECTED"; | |
| 484 if (state & (1 << STATE_TRAVERSED)) | |
| 485 result += " TRAVERSED"; | |
| 486 if (state & (1 << STATE_UNAVAILABLE)) | |
| 487 result += " UNAVAILABLE"; | |
| 488 if (state & (1 << STATE_VERTICAL)) | |
| 489 result += " VERTICAL"; | |
| 490 if (state & (1 << STATE_VISITED)) | |
| 491 result += " VISITED"; | |
| 492 | |
| 493 std::string tmp = UTF16ToUTF8(name); | |
| 494 RemoveChars(tmp, "\n", &tmp); | |
| 495 if (!tmp.empty()) | |
| 496 result += " name=" + tmp; | |
| 497 | |
| 498 tmp = UTF16ToUTF8(value); | |
| 499 RemoveChars(tmp, "\n", &tmp); | |
| 500 if (!tmp.empty()) | |
| 501 result += " value=" + tmp; | |
| 502 | |
| 503 result += " (" + IntToString(location.x()) + ", " + | |
| 504 IntToString(location.y()) + ")-(" + | |
| 505 IntToString(location.width()) + ", " + | |
| 506 IntToString(location.height()) + ")"; | |
| 507 | |
| 508 for (std::map<IntAttribute, int32>::const_iterator iter = | |
| 509 int_attributes.begin(); | |
| 510 iter != int_attributes.end(); | |
| 511 ++iter) { | |
| 512 std::string value = IntToString(iter->second); | |
| 513 switch (iter->first) { | |
| 514 case ATTR_SCROLL_X: | |
| 515 result += " scroll_x=" + value; | |
| 516 break; | |
| 517 case ATTR_SCROLL_X_MIN: | |
| 518 result += " scroll_x_min=" + value; | |
| 519 break; | |
| 520 case ATTR_SCROLL_X_MAX: | |
| 521 result += " scroll_x_max=" + value; | |
| 522 break; | |
| 523 case ATTR_SCROLL_Y: | |
| 524 result += " scroll_y=" + value; | |
| 525 break; | |
| 526 case ATTR_SCROLL_Y_MIN: | |
| 527 result += " scroll_y_min=" + value; | |
| 528 break; | |
| 529 case ATTR_SCROLL_Y_MAX: | |
| 530 result += " scroll_y_max=" + value; | |
| 531 break; | |
| 532 case ATTR_HIERARCHICAL_LEVEL: | |
| 533 result += " level=" + value; | |
| 534 break; | |
| 535 case ATTR_TEXT_SEL_START: | |
| 536 result += " sel_start=" + value; | |
| 537 break; | |
| 538 case ATTR_TEXT_SEL_END: | |
| 539 result += " sel_end=" + value; | |
| 540 break; | |
| 541 case ATTR_TABLE_ROW_COUNT: | |
| 542 result += " rows=" + value; | |
| 543 break; | |
| 544 case ATTR_TABLE_COLUMN_COUNT: | |
| 545 result += " cols=" + value; | |
| 546 break; | |
| 547 case ATTR_TABLE_CELL_COLUMN_INDEX: | |
| 548 result += " col=" + value; | |
| 549 break; | |
| 550 case ATTR_TABLE_CELL_ROW_INDEX: | |
| 551 result += " row=" + value; | |
| 552 break; | |
| 553 case ATTR_TABLE_CELL_COLUMN_SPAN: | |
| 554 result += " colspan=" + value; | |
| 555 break; | |
| 556 case ATTR_TABLE_CELL_ROW_SPAN: | |
| 557 result += " rowspan=" + value; | |
| 558 break; | |
| 559 case ATTR_TITLE_UI_ELEMENT: | |
| 560 result += " title_elem=" + value; | |
| 561 break; | |
| 562 } | |
| 563 } | |
| 564 | |
| 565 for (std::map<StringAttribute, string16>::const_iterator iter = | |
| 566 string_attributes.begin(); | |
| 567 iter != string_attributes.end(); | |
| 568 ++iter) { | |
| 569 std::string value = UTF16ToUTF8(iter->second); | |
| 570 switch (iter->first) { | |
| 571 case ATTR_DOC_URL: | |
| 572 result += " doc_url=" + value; | |
| 573 break; | |
| 574 case ATTR_DOC_TITLE: | |
| 575 result += " doc_title=" + value; | |
| 576 break; | |
| 577 case ATTR_DOC_MIMETYPE: | |
| 578 result += " doc_mimetype=" + value; | |
| 579 break; | |
| 580 case ATTR_DOC_DOCTYPE: | |
| 581 result += " doc_doctype=" + value; | |
| 582 break; | |
| 583 case ATTR_ACCESS_KEY: | |
| 584 result += " access_key=" + value; | |
| 585 break; | |
| 586 case ATTR_ACTION: | |
| 587 result += " action=" + value; | |
| 588 break; | |
| 589 case ATTR_DESCRIPTION: | |
| 590 result += " description=" + value; | |
| 591 break; | |
| 592 case ATTR_DISPLAY: | |
| 593 result += " display=" + value; | |
| 594 break; | |
| 595 case ATTR_HELP: | |
| 596 result += " help=" + value; | |
| 597 break; | |
| 598 case ATTR_HTML_TAG: | |
| 599 result += " html_tag=" + value; | |
| 600 break; | |
| 601 case ATTR_LIVE_RELEVANT: | |
| 602 result += " relevant=" + value; | |
| 603 break; | |
| 604 case ATTR_LIVE_STATUS: | |
| 605 result += " live=" + value; | |
| 606 break; | |
| 607 case ATTR_CONTAINER_LIVE_RELEVANT: | |
| 608 result += " container_relevant=" + value; | |
| 609 break; | |
| 610 case ATTR_CONTAINER_LIVE_STATUS: | |
| 611 result += " container_live=" + value; | |
| 612 break; | |
| 613 case ATTR_ROLE: | |
| 614 result += " role=" + value; | |
| 615 break; | |
| 616 case ATTR_SHORTCUT: | |
| 617 result += " shortcut=" + value; | |
| 618 break; | |
| 619 case ATTR_URL: | |
| 620 result += " url=" + value; | |
| 621 break; | |
| 622 } | |
| 623 } | |
| 624 | |
| 625 for (std::map<FloatAttribute, float>::const_iterator iter = | |
| 626 float_attributes.begin(); | |
| 627 iter != float_attributes.end(); | |
| 628 ++iter) { | |
| 629 std::string value = DoubleToString(iter->second); | |
| 630 switch (iter->first) { | |
| 631 case ATTR_DOC_LOADING_PROGRESS: | |
| 632 result += " doc_progress=" + value; | |
| 633 break; | |
| 634 case ATTR_VALUE_FOR_RANGE: | |
| 635 result += " value_for_range=" + value; | |
| 636 break; | |
| 637 case ATTR_MAX_VALUE_FOR_RANGE: | |
| 638 result += " max_value=" + value; | |
| 639 break; | |
| 640 case ATTR_MIN_VALUE_FOR_RANGE: | |
| 641 result += " min_value=" + value; | |
| 642 break; | |
| 643 } | |
| 644 } | |
| 645 | |
| 646 for (std::map<BoolAttribute, bool>::const_iterator iter = | |
| 647 bool_attributes.begin(); | |
| 648 iter != bool_attributes.end(); | |
| 649 ++iter) { | |
| 650 std::string value = iter->second ? "true" : "false"; | |
| 651 switch (iter->first) { | |
| 652 case ATTR_DOC_LOADED: | |
| 653 result += " doc_loaded=" + value; | |
| 654 break; | |
| 655 case ATTR_BUTTON_MIXED: | |
| 656 result += " mixed=" + value; | |
| 657 break; | |
| 658 case ATTR_LIVE_ATOMIC: | |
| 659 result += " atomic=" + value; | |
| 660 break; | |
| 661 case ATTR_LIVE_BUSY: | |
| 662 result += " busy=" + value; | |
| 663 break; | |
| 664 case ATTR_CONTAINER_LIVE_ATOMIC: | |
| 665 result += " container_atomic=" + value; | |
| 666 break; | |
| 667 case ATTR_CONTAINER_LIVE_BUSY: | |
| 668 result += " container_busy=" + value; | |
| 669 break; | |
| 670 case ATTR_ARIA_READONLY: | |
| 671 result += " aria_readonly=" + value; | |
| 672 break; | |
| 673 case ATTR_CAN_SET_VALUE: | |
| 674 result += " can_set_value=" + value; | |
| 675 break; | |
| 676 } | |
| 677 } | |
| 678 | |
| 679 if (!children.empty()) | |
| 680 result += " children=" + IntToString(children.size()); | |
| 681 | |
| 682 if (!indirect_child_ids.empty()) | |
| 683 result += " indirect_child_ids=" + IntVectorToString(indirect_child_ids); | |
| 684 | |
| 685 if (!line_breaks.empty()) | |
| 686 result += " line_breaks=" + IntVectorToString(line_breaks); | |
| 687 | |
| 688 if (!cell_ids.empty()) | |
| 689 result += " cell_ids=" + IntVectorToString(cell_ids); | |
| 690 | |
| 691 if (recursive) { | |
| 692 result += "\n"; | |
| 693 ++indent; | |
| 694 for (size_t i = 0; i < children.size(); ++i) | |
| 695 result += children[i].DebugString(true); | |
| 696 --indent; | |
| 697 } | |
| 698 | |
| 699 return result; | |
| 700 } | |
| 701 #endif // ifndef NDEBUG | |
| 702 | |
| 703 void WebAccessibility::Init(const WebKit::WebAccessibilityObject& src, | |
| 704 IncludeChildren include_children, | |
| 705 IncludeLineBreaks include_line_breaks) { | |
| 706 name = src.title(); | |
| 707 role = ConvertRole(src.roleValue()); | |
| 708 state = ConvertState(src); | |
| 709 location = src.boundingBoxRect(); | |
| 710 id = src.axID(); | |
| 711 | |
| 712 if (src.valueDescription().length()) | |
| 713 value = src.valueDescription(); | |
| 714 else | |
| 715 value = src.stringValue(); | |
| 716 | |
| 717 if (src.accessKey().length()) | |
| 718 string_attributes[ATTR_ACCESS_KEY] = src.accessKey(); | |
| 719 if (src.actionVerb().length()) | |
| 720 string_attributes[ATTR_ACTION] = src.actionVerb(); | |
| 721 if (src.isAriaReadOnly()) | |
| 722 bool_attributes[ATTR_ARIA_READONLY] = true; | |
| 723 if (src.isButtonStateMixed()) | |
| 724 bool_attributes[ATTR_BUTTON_MIXED] = true; | |
| 725 if (src.canSetValueAttribute()) | |
| 726 bool_attributes[ATTR_CAN_SET_VALUE] = true; | |
| 727 if (src.accessibilityDescription().length()) | |
| 728 string_attributes[ATTR_DESCRIPTION] = src.accessibilityDescription(); | |
| 729 if (src.hasComputedStyle()) | |
| 730 string_attributes[ATTR_DISPLAY] = src.computedStyleDisplay(); | |
| 731 if (src.helpText().length()) | |
| 732 string_attributes[ATTR_HELP] = src.helpText(); | |
| 733 if (src.keyboardShortcut().length()) | |
| 734 string_attributes[ATTR_SHORTCUT] = src.keyboardShortcut(); | |
| 735 if (src.titleUIElement().isValid()) | |
| 736 int_attributes[ATTR_TITLE_UI_ELEMENT] = src.titleUIElement().axID(); | |
| 737 if (!src.url().isEmpty()) | |
| 738 string_attributes[ATTR_URL] = src.url().spec().utf16(); | |
| 739 | |
| 740 if (role == ROLE_TREE_ITEM) | |
| 741 int_attributes[ATTR_HIERARCHICAL_LEVEL] = src.hierarchicalLevel(); | |
| 742 | |
| 743 if (role == ROLE_SLIDER) | |
| 744 include_children = NO_CHILDREN; | |
| 745 | |
| 746 // Treat the active list box item as focused. | |
| 747 if (role == ROLE_LISTBOX_OPTION && src.isSelectedOptionActive()) | |
| 748 state |= (1 << WebAccessibility::STATE_FOCUSED); | |
| 749 | |
| 750 WebKit::WebNode node = src.node(); | |
| 751 bool is_iframe = false; | |
| 752 | |
| 753 if (!node.isNull() && node.isElementNode()) { | |
| 754 WebKit::WebElement element = node.to<WebKit::WebElement>(); | |
| 755 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); | |
| 756 | |
| 757 // TODO(ctguil): The tagName in WebKit is lower cased but | |
| 758 // HTMLElement::nodeName calls localNameUpper. Consider adding | |
| 759 // a WebElement method that returns the original lower cased tagName. | |
| 760 string_attributes[ATTR_HTML_TAG] = | |
| 761 StringToLowerASCII(string16(element.tagName())); | |
| 762 for (unsigned i = 0; i < element.attributeCount(); ++i) { | |
| 763 string16 name = StringToLowerASCII(string16( | |
| 764 element.attributeLocalName(i))); | |
| 765 string16 value = element.attributeValue(i); | |
| 766 html_attributes.push_back(std::pair<string16, string16>(name, value)); | |
| 767 } | |
| 768 | |
| 769 if (role == ROLE_EDITABLE_TEXT || | |
| 770 role == ROLE_TEXTAREA || | |
| 771 role == ROLE_TEXT_FIELD) { | |
| 772 // Jaws gets confused by children of text fields, so we ignore them. | |
| 773 include_children = NO_CHILDREN; | |
| 774 | |
| 775 int_attributes[ATTR_TEXT_SEL_START] = src.selectionStart(); | |
| 776 int_attributes[ATTR_TEXT_SEL_END] = src.selectionEnd(); | |
| 777 | |
| 778 if (include_line_breaks == INCLUDE_LINE_BREAKS) { | |
| 779 WebKit::WebVector<int> src_line_breaks; | |
| 780 src.lineBreaks(src_line_breaks); | |
| 781 line_breaks.reserve(src_line_breaks.size()); | |
| 782 for (size_t i = 0; i < src_line_breaks.size(); ++i) | |
| 783 line_breaks.push_back(src_line_breaks[i]); | |
| 784 } | |
| 785 } | |
| 786 | |
| 787 // ARIA role. | |
| 788 if (element.hasAttribute("role")) { | |
| 789 string_attributes[ATTR_ROLE] = element.getAttribute("role"); | |
| 790 } | |
| 791 | |
| 792 // Live region attributes | |
| 793 if (element.hasAttribute("aria-atomic")) { | |
| 794 bool_attributes[ATTR_LIVE_ATOMIC] = | |
| 795 LowerCaseEqualsASCII(element.getAttribute("aria-atomic"), "true"); | |
| 796 } | |
| 797 if (element.hasAttribute("aria-busy")) { | |
| 798 bool_attributes[ATTR_LIVE_BUSY] = | |
| 799 LowerCaseEqualsASCII(element.getAttribute("aria-busy"), "true"); | |
| 800 } | |
| 801 if (element.hasAttribute("aria-live")) { | |
| 802 string_attributes[ATTR_LIVE_STATUS] = element.getAttribute("aria-live"); | |
| 803 } | |
| 804 if (element.hasAttribute("aria-relevant")) { | |
| 805 string_attributes[ATTR_LIVE_RELEVANT] = | |
| 806 element.getAttribute("aria-relevant"); | |
| 807 } | |
| 808 } | |
| 809 | |
| 810 // Walk up the parent chain to set live region attributes of containers | |
| 811 | |
| 812 WebKit::WebAccessibilityObject container_accessible = src; | |
| 813 while (!container_accessible.isNull()) { | |
| 814 WebKit::WebNode container_node = container_accessible.node(); | |
| 815 if (!container_node.isNull() && container_node.isElementNode()) { | |
| 816 WebKit::WebElement container_elem = | |
| 817 container_node.to<WebKit::WebElement>(); | |
| 818 if (container_elem.hasAttribute("aria-atomic") && | |
| 819 bool_attributes.find(ATTR_CONTAINER_LIVE_ATOMIC) == | |
| 820 bool_attributes.end()) { | |
| 821 bool_attributes[ATTR_CONTAINER_LIVE_ATOMIC] = | |
| 822 LowerCaseEqualsASCII(container_elem.getAttribute("aria-atomic"), | |
| 823 "true"); | |
| 824 } | |
| 825 if (container_elem.hasAttribute("aria-busy") && | |
| 826 bool_attributes.find(ATTR_CONTAINER_LIVE_BUSY) == | |
| 827 bool_attributes.end()) { | |
| 828 bool_attributes[ATTR_CONTAINER_LIVE_BUSY] = | |
| 829 LowerCaseEqualsASCII(container_elem.getAttribute("aria-busy"), | |
| 830 "true"); | |
| 831 } | |
| 832 if (container_elem.hasAttribute("aria-live") && | |
| 833 string_attributes.find(ATTR_CONTAINER_LIVE_STATUS) == | |
| 834 string_attributes.end()) { | |
| 835 string_attributes[ATTR_CONTAINER_LIVE_STATUS] = | |
| 836 container_elem.getAttribute("aria-live"); | |
| 837 } | |
| 838 if (container_elem.hasAttribute("aria-relevant") && | |
| 839 string_attributes.find(ATTR_CONTAINER_LIVE_RELEVANT) == | |
| 840 string_attributes.end()) { | |
| 841 string_attributes[ATTR_CONTAINER_LIVE_RELEVANT] = | |
| 842 container_elem.getAttribute("aria-relevant"); | |
| 843 } | |
| 844 } | |
| 845 container_accessible = container_accessible.parentObject(); | |
| 846 } | |
| 847 | |
| 848 if (role == WebAccessibility::ROLE_PROGRESS_INDICATOR || | |
| 849 role == WebAccessibility::ROLE_SCROLLBAR || | |
| 850 role == WebAccessibility::ROLE_SLIDER) { | |
| 851 float_attributes[ATTR_VALUE_FOR_RANGE] = src.valueForRange(); | |
| 852 float_attributes[ATTR_MAX_VALUE_FOR_RANGE] = src.minValueForRange(); | |
| 853 float_attributes[ATTR_MIN_VALUE_FOR_RANGE] = src.maxValueForRange(); | |
| 854 } | |
| 855 | |
| 856 if (role == WebAccessibility::ROLE_DOCUMENT || | |
| 857 role == WebAccessibility::ROLE_WEB_AREA) { | |
| 858 const WebKit::WebDocument& document = src.document(); | |
| 859 if (name.empty()) | |
| 860 name = document.title(); | |
| 861 string_attributes[ATTR_DOC_TITLE] = document.title(); | |
| 862 string_attributes[ATTR_DOC_URL] = document.url().spec().utf16(); | |
| 863 if (document.isXHTMLDocument()) | |
| 864 string_attributes[ATTR_DOC_MIMETYPE] = WebKit::WebString("text/xhtml"); | |
| 865 else | |
| 866 string_attributes[ATTR_DOC_MIMETYPE] = WebKit::WebString("text/html"); | |
| 867 bool_attributes[ATTR_DOC_LOADED] = src.isLoaded(); | |
| 868 float_attributes[ATTR_DOC_LOADING_PROGRESS] = | |
| 869 src.estimatedLoadingProgress(); | |
| 870 | |
| 871 const WebKit::WebDocumentType& doctype = document.doctype(); | |
| 872 if (!doctype.isNull()) | |
| 873 string_attributes[ATTR_DOC_DOCTYPE] = doctype.name(); | |
| 874 | |
| 875 const gfx::Size& scroll_offset = document.frame()->scrollOffset(); | |
| 876 int_attributes[ATTR_SCROLL_X] = scroll_offset.width(); | |
| 877 int_attributes[ATTR_SCROLL_Y] = scroll_offset.height(); | |
| 878 | |
| 879 const gfx::Size& min_offset = document.frame()->minimumScrollOffset(); | |
| 880 int_attributes[ATTR_SCROLL_X_MIN] = min_offset.width(); | |
| 881 int_attributes[ATTR_SCROLL_Y_MIN] = min_offset.height(); | |
| 882 | |
| 883 const gfx::Size& max_offset = document.frame()->maximumScrollOffset(); | |
| 884 int_attributes[ATTR_SCROLL_X_MAX] = max_offset.width(); | |
| 885 int_attributes[ATTR_SCROLL_Y_MAX] = max_offset.height(); | |
| 886 } | |
| 887 | |
| 888 if (role == WebAccessibility::ROLE_TABLE) { | |
| 889 int column_count = src.columnCount(); | |
| 890 int row_count = src.rowCount(); | |
| 891 if (column_count > 0 && row_count > 0) { | |
| 892 std::set<int> unique_cell_id_set; | |
| 893 int_attributes[ATTR_TABLE_COLUMN_COUNT] = column_count; | |
| 894 int_attributes[ATTR_TABLE_ROW_COUNT] = row_count; | |
| 895 for (int i = 0; i < column_count * row_count; ++i) { | |
| 896 WebAccessibilityObject cell = src.cellForColumnAndRow( | |
| 897 i % column_count, i / column_count); | |
| 898 int cell_id = -1; | |
| 899 if (!cell.isNull()) { | |
| 900 cell_id = cell.axID(); | |
| 901 if (unique_cell_id_set.find(cell_id) == unique_cell_id_set.end()) { | |
| 902 unique_cell_id_set.insert(cell_id); | |
| 903 unique_cell_ids.push_back(cell_id); | |
| 904 } | |
| 905 } | |
| 906 cell_ids.push_back(cell_id); | |
| 907 } | |
| 908 } | |
| 909 } | |
| 910 | |
| 911 if (role == WebAccessibility::ROLE_CELL || | |
| 912 role == WebAccessibility::ROLE_ROW_HEADER || | |
| 913 role == WebAccessibility::ROLE_COLUMN_HEADER) { | |
| 914 int_attributes[ATTR_TABLE_CELL_COLUMN_INDEX] = src.cellColumnIndex(); | |
| 915 int_attributes[ATTR_TABLE_CELL_COLUMN_SPAN] = src.cellColumnSpan(); | |
| 916 int_attributes[ATTR_TABLE_CELL_ROW_INDEX] = src.cellRowIndex(); | |
| 917 int_attributes[ATTR_TABLE_CELL_ROW_SPAN] = src.cellRowSpan(); | |
| 918 } | |
| 919 | |
| 920 if (include_children == INCLUDE_CHILDREN) { | |
| 921 // Recursively create children. | |
| 922 int child_count = src.childCount(); | |
| 923 std::set<int32> child_ids; | |
| 924 for (int i = 0; i < child_count; ++i) { | |
| 925 WebAccessibilityObject child = src.childAt(i); | |
| 926 int32 child_id = child.axID(); | |
| 927 | |
| 928 // The child may be invalid due to issues in webkit accessibility code. | |
| 929 // Don't add children that are invalid thus preventing a crash. | |
| 930 // https://bugs.webkit.org/show_bug.cgi?id=44149 | |
| 931 // TODO(ctguil): We may want to remove this check as webkit stabilizes. | |
| 932 if (!child.isValid()) | |
| 933 continue; | |
| 934 | |
| 935 // Children may duplicated in the webkit accessibility tree. Only add a | |
| 936 // child once for the web accessibility tree. | |
| 937 // https://bugs.webkit.org/show_bug.cgi?id=58930 | |
| 938 if (child_ids.find(child_id) != child_ids.end()) | |
| 939 continue; | |
| 940 child_ids.insert(child_id); | |
| 941 | |
| 942 // Some nodes appear in the tree in more than one place: for example, | |
| 943 // a cell in a table appears as a child of both a row and a column. | |
| 944 // Only recursively add child nodes that have this node as its | |
| 945 // unignored parent. For child nodes that are actually parented to | |
| 946 // somethinng else, store only the ID. | |
| 947 // | |
| 948 // As an exception, also add children of an iframe element. | |
| 949 // https://bugs.webkit.org/show_bug.cgi?id=57066 | |
| 950 if (is_iframe || IsParentUnignoredOf(src, child)) { | |
| 951 children.push_back( | |
| 952 WebAccessibility(child, include_children, include_line_breaks)); | |
| 953 } else { | |
| 954 indirect_child_ids.push_back(child_id); | |
| 955 } | |
| 956 } | |
| 957 } | |
| 958 } | |
| 959 | |
| 960 bool WebAccessibility::IsParentUnignoredOf( | |
| 961 const WebKit::WebAccessibilityObject& ancestor, | |
| 962 const WebKit::WebAccessibilityObject& child) { | |
| 963 WebKit::WebAccessibilityObject parent = child.parentObject(); | |
| 964 while (!parent.isNull() && parent.accessibilityIsIgnored()) | |
| 965 parent = parent.parentObject(); | |
| 966 return parent.equals(ancestor); | |
| 967 } | |
| 968 | |
| 969 } // namespace webkit_glue | |
| OLD | NEW |