| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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 "components/test_runner/web_ax_object_proxy.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 | |
| 9 #include "base/macros.h" | |
| 10 #include "base/strings/stringprintf.h" | |
| 11 #include "gin/handle.h" | |
| 12 #include "third_party/WebKit/public/platform/WebFloatRect.h" | |
| 13 #include "third_party/WebKit/public/platform/WebPoint.h" | |
| 14 #include "third_party/WebKit/public/platform/WebRect.h" | |
| 15 #include "third_party/WebKit/public/platform/WebString.h" | |
| 16 #include "third_party/WebKit/public/web/WebFrame.h" | |
| 17 #include "third_party/WebKit/public/web/WebKit.h" | |
| 18 #include "third_party/skia/include/core/SkMatrix44.h" | |
| 19 #include "ui/gfx/geometry/rect_f.h" | |
| 20 #include "ui/gfx/transform.h" | |
| 21 | |
| 22 namespace test_runner { | |
| 23 | |
| 24 namespace { | |
| 25 | |
| 26 // Map role value to string, matching Safari/Mac platform implementation to | |
| 27 // avoid rebaselining layout tests. | |
| 28 std::string RoleToString(blink::WebAXRole role) | |
| 29 { | |
| 30 std::string result = "AXRole: AX"; | |
| 31 switch (role) { | |
| 32 case blink::WebAXRoleAbbr: | |
| 33 return result.append("Abbr"); | |
| 34 case blink::WebAXRoleAlertDialog: | |
| 35 return result.append("AlertDialog"); | |
| 36 case blink::WebAXRoleAlert: | |
| 37 return result.append("Alert"); | |
| 38 case blink::WebAXRoleAnnotation: | |
| 39 return result.append("Annotation"); | |
| 40 case blink::WebAXRoleApplication: | |
| 41 return result.append("Application"); | |
| 42 case blink::WebAXRoleArticle: | |
| 43 return result.append("Article"); | |
| 44 case blink::WebAXRoleAudio: | |
| 45 return result.append("Audio"); | |
| 46 case blink::WebAXRoleBanner: | |
| 47 return result.append("Banner"); | |
| 48 case blink::WebAXRoleBlockquote: | |
| 49 return result.append("Blockquote"); | |
| 50 case blink::WebAXRoleBusyIndicator: | |
| 51 return result.append("BusyIndicator"); | |
| 52 case blink::WebAXRoleButton: | |
| 53 return result.append("Button"); | |
| 54 case blink::WebAXRoleCanvas: | |
| 55 return result.append("Canvas"); | |
| 56 case blink::WebAXRoleCaption: | |
| 57 return result.append("Caption"); | |
| 58 case blink::WebAXRoleCell: | |
| 59 return result.append("Cell"); | |
| 60 case blink::WebAXRoleCheckBox: | |
| 61 return result.append("CheckBox"); | |
| 62 case blink::WebAXRoleColorWell: | |
| 63 return result.append("ColorWell"); | |
| 64 case blink::WebAXRoleColumnHeader: | |
| 65 return result.append("ColumnHeader"); | |
| 66 case blink::WebAXRoleColumn: | |
| 67 return result.append("Column"); | |
| 68 case blink::WebAXRoleComboBox: | |
| 69 return result.append("ComboBox"); | |
| 70 case blink::WebAXRoleComplementary: | |
| 71 return result.append("Complementary"); | |
| 72 case blink::WebAXRoleContentInfo: | |
| 73 return result.append("ContentInfo"); | |
| 74 case blink::WebAXRoleDate: | |
| 75 return result.append("DateField"); | |
| 76 case blink::WebAXRoleDateTime: | |
| 77 return result.append("DateTimeField"); | |
| 78 case blink::WebAXRoleDefinition: | |
| 79 return result.append("Definition"); | |
| 80 case blink::WebAXRoleDescriptionListDetail: | |
| 81 return result.append("DescriptionListDetail"); | |
| 82 case blink::WebAXRoleDescriptionList: | |
| 83 return result.append("DescriptionList"); | |
| 84 case blink::WebAXRoleDescriptionListTerm: | |
| 85 return result.append("DescriptionListTerm"); | |
| 86 case blink::WebAXRoleDetails: | |
| 87 return result.append("Details"); | |
| 88 case blink::WebAXRoleDialog: | |
| 89 return result.append("Dialog"); | |
| 90 case blink::WebAXRoleDirectory: | |
| 91 return result.append("Directory"); | |
| 92 case blink::WebAXRoleDisclosureTriangle: | |
| 93 return result.append("DisclosureTriangle"); | |
| 94 case blink::WebAXRoleDiv: | |
| 95 return result.append("Div"); | |
| 96 case blink::WebAXRoleDocument: | |
| 97 return result.append("Document"); | |
| 98 case blink::WebAXRoleEmbeddedObject: | |
| 99 return result.append("EmbeddedObject"); | |
| 100 case blink::WebAXRoleFigcaption: | |
| 101 return result.append("Figcaption"); | |
| 102 case blink::WebAXRoleFigure: | |
| 103 return result.append("Figure"); | |
| 104 case blink::WebAXRoleFooter: | |
| 105 return result.append("Footer"); | |
| 106 case blink::WebAXRoleForm: | |
| 107 return result.append("Form"); | |
| 108 case blink::WebAXRoleGrid: | |
| 109 return result.append("Grid"); | |
| 110 case blink::WebAXRoleGroup: | |
| 111 return result.append("Group"); | |
| 112 case blink::WebAXRoleHeading: | |
| 113 return result.append("Heading"); | |
| 114 case blink::WebAXRoleIgnored: | |
| 115 return result.append("Ignored"); | |
| 116 case blink::WebAXRoleImageMapLink: | |
| 117 return result.append("ImageMapLink"); | |
| 118 case blink::WebAXRoleImageMap: | |
| 119 return result.append("ImageMap"); | |
| 120 case blink::WebAXRoleImage: | |
| 121 return result.append("Image"); | |
| 122 case blink::WebAXRoleInlineTextBox: | |
| 123 return result.append("InlineTextBox"); | |
| 124 case blink::WebAXRoleInputTime: | |
| 125 return result.append("InputTime"); | |
| 126 case blink::WebAXRoleLabel: | |
| 127 return result.append("Label"); | |
| 128 case blink::WebAXRoleLegend: | |
| 129 return result.append("Legend"); | |
| 130 case blink::WebAXRoleLink: | |
| 131 return result.append("Link"); | |
| 132 case blink::WebAXRoleLineBreak: | |
| 133 return result.append("LineBreak"); | |
| 134 case blink::WebAXRoleListBoxOption: | |
| 135 return result.append("ListBoxOption"); | |
| 136 case blink::WebAXRoleListBox: | |
| 137 return result.append("ListBox"); | |
| 138 case blink::WebAXRoleListItem: | |
| 139 return result.append("ListItem"); | |
| 140 case blink::WebAXRoleListMarker: | |
| 141 return result.append("ListMarker"); | |
| 142 case blink::WebAXRoleList: | |
| 143 return result.append("List"); | |
| 144 case blink::WebAXRoleLog: | |
| 145 return result.append("Log"); | |
| 146 case blink::WebAXRoleMain: | |
| 147 return result.append("Main"); | |
| 148 case blink::WebAXRoleMark: | |
| 149 return result.append("Mark"); | |
| 150 case blink::WebAXRoleMarquee: | |
| 151 return result.append("Marquee"); | |
| 152 case blink::WebAXRoleMath: | |
| 153 return result.append("Math"); | |
| 154 case blink::WebAXRoleMenuBar: | |
| 155 return result.append("MenuBar"); | |
| 156 case blink::WebAXRoleMenuButton: | |
| 157 return result.append("MenuButton"); | |
| 158 case blink::WebAXRoleMenuItem: | |
| 159 return result.append("MenuItem"); | |
| 160 case blink::WebAXRoleMenuItemCheckBox: | |
| 161 return result.append("MenuItemCheckBox"); | |
| 162 case blink::WebAXRoleMenuItemRadio: | |
| 163 return result.append("MenuItemRadio"); | |
| 164 case blink::WebAXRoleMenuListOption: | |
| 165 return result.append("MenuListOption"); | |
| 166 case blink::WebAXRoleMenuListPopup: | |
| 167 return result.append("MenuListPopup"); | |
| 168 case blink::WebAXRoleMenu: | |
| 169 return result.append("Menu"); | |
| 170 case blink::WebAXRoleMeter: | |
| 171 return result.append("Meter"); | |
| 172 case blink::WebAXRoleNavigation: | |
| 173 return result.append("Navigation"); | |
| 174 case blink::WebAXRoleNone: | |
| 175 return result.append("None"); | |
| 176 case blink::WebAXRoleNote: | |
| 177 return result.append("Note"); | |
| 178 case blink::WebAXRoleOutline: | |
| 179 return result.append("Outline"); | |
| 180 case blink::WebAXRoleParagraph: | |
| 181 return result.append("Paragraph"); | |
| 182 case blink::WebAXRolePopUpButton: | |
| 183 return result.append("PopUpButton"); | |
| 184 case blink::WebAXRolePre: | |
| 185 return result.append("Pre"); | |
| 186 case blink::WebAXRolePresentational: | |
| 187 return result.append("Presentational"); | |
| 188 case blink::WebAXRoleProgressIndicator: | |
| 189 return result.append("ProgressIndicator"); | |
| 190 case blink::WebAXRoleRadioButton: | |
| 191 return result.append("RadioButton"); | |
| 192 case blink::WebAXRoleRadioGroup: | |
| 193 return result.append("RadioGroup"); | |
| 194 case blink::WebAXRoleRegion: | |
| 195 return result.append("Region"); | |
| 196 case blink::WebAXRoleRootWebArea: | |
| 197 return result.append("RootWebArea"); | |
| 198 case blink::WebAXRoleRowHeader: | |
| 199 return result.append("RowHeader"); | |
| 200 case blink::WebAXRoleRow: | |
| 201 return result.append("Row"); | |
| 202 case blink::WebAXRoleRuby: | |
| 203 return result.append("Ruby"); | |
| 204 case blink::WebAXRoleRuler: | |
| 205 return result.append("Ruler"); | |
| 206 case blink::WebAXRoleSVGRoot: | |
| 207 return result.append("SVGRoot"); | |
| 208 case blink::WebAXRoleScrollArea: | |
| 209 return result.append("ScrollArea"); | |
| 210 case blink::WebAXRoleScrollBar: | |
| 211 return result.append("ScrollBar"); | |
| 212 case blink::WebAXRoleSeamlessWebArea: | |
| 213 return result.append("SeamlessWebArea"); | |
| 214 case blink::WebAXRoleSearch: | |
| 215 return result.append("Search"); | |
| 216 case blink::WebAXRoleSearchBox: | |
| 217 return result.append("SearchBox"); | |
| 218 case blink::WebAXRoleSlider: | |
| 219 return result.append("Slider"); | |
| 220 case blink::WebAXRoleSliderThumb: | |
| 221 return result.append("SliderThumb"); | |
| 222 case blink::WebAXRoleSpinButtonPart: | |
| 223 return result.append("SpinButtonPart"); | |
| 224 case blink::WebAXRoleSpinButton: | |
| 225 return result.append("SpinButton"); | |
| 226 case blink::WebAXRoleSplitter: | |
| 227 return result.append("Splitter"); | |
| 228 case blink::WebAXRoleStaticText: | |
| 229 return result.append("StaticText"); | |
| 230 case blink::WebAXRoleStatus: | |
| 231 return result.append("Status"); | |
| 232 case blink::WebAXRoleSwitch: | |
| 233 return result.append("Switch"); | |
| 234 case blink::WebAXRoleTabGroup: | |
| 235 return result.append("TabGroup"); | |
| 236 case blink::WebAXRoleTabList: | |
| 237 return result.append("TabList"); | |
| 238 case blink::WebAXRoleTabPanel: | |
| 239 return result.append("TabPanel"); | |
| 240 case blink::WebAXRoleTab: | |
| 241 return result.append("Tab"); | |
| 242 case blink::WebAXRoleTableHeaderContainer: | |
| 243 return result.append("TableHeaderContainer"); | |
| 244 case blink::WebAXRoleTable: | |
| 245 return result.append("Table"); | |
| 246 case blink::WebAXRoleTextField: | |
| 247 return result.append("TextField"); | |
| 248 case blink::WebAXRoleTime: | |
| 249 return result.append("Time"); | |
| 250 case blink::WebAXRoleTimer: | |
| 251 return result.append("Timer"); | |
| 252 case blink::WebAXRoleToggleButton: | |
| 253 return result.append("ToggleButton"); | |
| 254 case blink::WebAXRoleToolbar: | |
| 255 return result.append("Toolbar"); | |
| 256 case blink::WebAXRoleTreeGrid: | |
| 257 return result.append("TreeGrid"); | |
| 258 case blink::WebAXRoleTreeItem: | |
| 259 return result.append("TreeItem"); | |
| 260 case blink::WebAXRoleTree: | |
| 261 return result.append("Tree"); | |
| 262 case blink::WebAXRoleUnknown: | |
| 263 return result.append("Unknown"); | |
| 264 case blink::WebAXRoleUserInterfaceTooltip: | |
| 265 return result.append("UserInterfaceTooltip"); | |
| 266 case blink::WebAXRoleVideo: | |
| 267 return result.append("Video"); | |
| 268 case blink::WebAXRoleWebArea: | |
| 269 return result.append("WebArea"); | |
| 270 case blink::WebAXRoleWindow: | |
| 271 return result.append("Window"); | |
| 272 default: | |
| 273 return result.append("Unknown"); | |
| 274 } | |
| 275 } | |
| 276 | |
| 277 std::string GetStringValue(const blink::WebAXObject& object) { | |
| 278 std::string value; | |
| 279 if (object.role() == blink::WebAXRoleColorWell) { | |
| 280 unsigned int color = object.colorValue(); | |
| 281 unsigned int red = (color >> 16) & 0xFF; | |
| 282 unsigned int green = (color >> 8) & 0xFF; | |
| 283 unsigned int blue = color & 0xFF; | |
| 284 value = base::StringPrintf("rgba(%d, %d, %d, 1)", | |
| 285 red, green, blue); | |
| 286 } else { | |
| 287 value = object.stringValue().utf8(); | |
| 288 } | |
| 289 return value.insert(0, "AXValue: "); | |
| 290 } | |
| 291 | |
| 292 std::string GetRole(const blink::WebAXObject& object) { | |
| 293 std::string role_string = RoleToString(object.role()); | |
| 294 | |
| 295 // Special-case canvas with fallback content because Chromium wants to treat | |
| 296 // this as essentially a separate role that it can map differently depending | |
| 297 // on the platform. | |
| 298 if (object.role() == blink::WebAXRoleCanvas && | |
| 299 object.canvasHasFallbackContent()) { | |
| 300 role_string += "WithFallbackContent"; | |
| 301 } | |
| 302 | |
| 303 return role_string; | |
| 304 } | |
| 305 | |
| 306 std::string GetValueDescription(const blink::WebAXObject& object) { | |
| 307 std::string value_description = object.valueDescription().utf8(); | |
| 308 return value_description.insert(0, "AXValueDescription: "); | |
| 309 } | |
| 310 | |
| 311 std::string GetLanguage(const blink::WebAXObject& object) { | |
| 312 std::string language = object.language().utf8(); | |
| 313 return language.insert(0, "AXLanguage: "); | |
| 314 } | |
| 315 | |
| 316 std::string GetAttributes(const blink::WebAXObject& object) { | |
| 317 std::string attributes(object.name().utf8()); | |
| 318 attributes.append("\n"); | |
| 319 attributes.append(GetRole(object)); | |
| 320 return attributes; | |
| 321 } | |
| 322 | |
| 323 // New bounds calculation algorithm. Retrieves the frame-relative bounds | |
| 324 // of an object by calling getRelativeBounds and then applying the offsets | |
| 325 // and transforms recursively on each container of this object. | |
| 326 blink::WebFloatRect BoundsForObject(const blink::WebAXObject& object) { | |
| 327 blink::WebAXObject container; | |
| 328 blink::WebFloatRect bounds; | |
| 329 SkMatrix44 matrix; | |
| 330 object.getRelativeBounds(container, bounds, matrix); | |
| 331 gfx::RectF computedBounds(0, 0, bounds.width, bounds.height); | |
| 332 while (!container.isDetached()) { | |
| 333 computedBounds.Offset(bounds.x, bounds.y); | |
| 334 computedBounds.Offset( | |
| 335 -container.getScrollOffset().x, -container.getScrollOffset().y); | |
| 336 if (!matrix.isIdentity()) { | |
| 337 gfx::Transform transform(matrix); | |
| 338 transform.TransformRect(&computedBounds); | |
| 339 } | |
| 340 container.getRelativeBounds(container, bounds, matrix); | |
| 341 } | |
| 342 return blink::WebFloatRect(computedBounds.x(), | |
| 343 computedBounds.y(), | |
| 344 computedBounds.width(), | |
| 345 computedBounds.height()); | |
| 346 } | |
| 347 | |
| 348 blink::WebRect BoundsForCharacter(const blink::WebAXObject& object, | |
| 349 int characterIndex) { | |
| 350 DCHECK_EQ(object.role(), blink::WebAXRoleStaticText); | |
| 351 int end = 0; | |
| 352 for (unsigned i = 0; i < object.childCount(); i++) { | |
| 353 blink::WebAXObject inline_text_box = object.childAt(i); | |
| 354 DCHECK_EQ(inline_text_box.role(), blink::WebAXRoleInlineTextBox); | |
| 355 int start = end; | |
| 356 blink::WebString name = inline_text_box.name(); | |
| 357 end += name.length(); | |
| 358 if (characterIndex < start || characterIndex >= end) | |
| 359 continue; | |
| 360 | |
| 361 blink::WebFloatRect inline_text_box_rect = BoundsForObject(inline_text_box); | |
| 362 | |
| 363 int localIndex = characterIndex - start; | |
| 364 blink::WebVector<int> character_offsets; | |
| 365 inline_text_box.characterOffsets(character_offsets); | |
| 366 if (character_offsets.size() != name.length()) | |
| 367 return blink::WebRect(); | |
| 368 | |
| 369 switch (inline_text_box.textDirection()) { | |
| 370 case blink::WebAXTextDirectionLR: { | |
| 371 if (localIndex) { | |
| 372 int left = inline_text_box_rect.x + character_offsets[localIndex - 1]; | |
| 373 int width = character_offsets[localIndex] - | |
| 374 character_offsets[localIndex - 1]; | |
| 375 return blink::WebRect(left, inline_text_box_rect.y, | |
| 376 width, inline_text_box_rect.height); | |
| 377 } | |
| 378 return blink::WebRect( | |
| 379 inline_text_box_rect.x, inline_text_box_rect.y, | |
| 380 character_offsets[0], inline_text_box_rect.height); | |
| 381 } | |
| 382 case blink::WebAXTextDirectionRL: { | |
| 383 int right = inline_text_box_rect.x + inline_text_box_rect.width; | |
| 384 | |
| 385 if (localIndex) { | |
| 386 int left = right - character_offsets[localIndex]; | |
| 387 int width = character_offsets[localIndex] - | |
| 388 character_offsets[localIndex - 1]; | |
| 389 return blink::WebRect(left, inline_text_box_rect.y, | |
| 390 width, inline_text_box_rect.height); | |
| 391 } | |
| 392 int left = right - character_offsets[0]; | |
| 393 return blink::WebRect( | |
| 394 left, inline_text_box_rect.y, | |
| 395 character_offsets[0], inline_text_box_rect.height); | |
| 396 } | |
| 397 case blink::WebAXTextDirectionTB: { | |
| 398 if (localIndex) { | |
| 399 int top = inline_text_box_rect.y + character_offsets[localIndex - 1]; | |
| 400 int height = character_offsets[localIndex] - | |
| 401 character_offsets[localIndex - 1]; | |
| 402 return blink::WebRect(inline_text_box_rect.x, top, | |
| 403 inline_text_box_rect.width, height); | |
| 404 } | |
| 405 return blink::WebRect(inline_text_box_rect.x, inline_text_box_rect.y, | |
| 406 inline_text_box_rect.width, character_offsets[0]); | |
| 407 } | |
| 408 case blink::WebAXTextDirectionBT: { | |
| 409 int bottom = inline_text_box_rect.y + inline_text_box_rect.height; | |
| 410 | |
| 411 if (localIndex) { | |
| 412 int top = bottom - character_offsets[localIndex]; | |
| 413 int height = character_offsets[localIndex] - | |
| 414 character_offsets[localIndex - 1]; | |
| 415 return blink::WebRect(inline_text_box_rect.x, top, | |
| 416 inline_text_box_rect.width, height); | |
| 417 } | |
| 418 int top = bottom - character_offsets[0]; | |
| 419 return blink::WebRect(inline_text_box_rect.x, top, | |
| 420 inline_text_box_rect.width, character_offsets[0]); | |
| 421 } | |
| 422 } | |
| 423 } | |
| 424 | |
| 425 DCHECK(false); | |
| 426 return blink::WebRect(); | |
| 427 } | |
| 428 | |
| 429 std::vector<std::string> GetMisspellings(blink::WebAXObject& object) { | |
| 430 std::vector<std::string> misspellings; | |
| 431 std::string text(object.name().utf8()); | |
| 432 | |
| 433 blink::WebVector<blink::WebAXMarkerType> marker_types; | |
| 434 blink::WebVector<int> marker_starts; | |
| 435 blink::WebVector<int> marker_ends; | |
| 436 object.markers(marker_types, marker_starts, marker_ends); | |
| 437 DCHECK_EQ(marker_types.size(), marker_starts.size()); | |
| 438 DCHECK_EQ(marker_starts.size(), marker_ends.size()); | |
| 439 | |
| 440 for (size_t i = 0; i < marker_types.size(); ++i) { | |
| 441 if (marker_types[i] & blink::WebAXMarkerTypeSpelling) { | |
| 442 misspellings.push_back( | |
| 443 text.substr(marker_starts[i], marker_ends[i] - marker_starts[i])); | |
| 444 } | |
| 445 } | |
| 446 | |
| 447 return misspellings; | |
| 448 } | |
| 449 | |
| 450 void GetBoundariesForOneWord(const blink::WebAXObject& object, | |
| 451 int character_index, | |
| 452 int& word_start, | |
| 453 int& word_end) { | |
| 454 int end = 0; | |
| 455 for (size_t i = 0; i < object.childCount(); i++) { | |
| 456 blink::WebAXObject inline_text_box = object.childAt(i); | |
| 457 DCHECK_EQ(inline_text_box.role(), blink::WebAXRoleInlineTextBox); | |
| 458 int start = end; | |
| 459 blink::WebString name = inline_text_box.name(); | |
| 460 end += name.length(); | |
| 461 if (end <= character_index) | |
| 462 continue; | |
| 463 int localIndex = character_index - start; | |
| 464 | |
| 465 blink::WebVector<int> starts; | |
| 466 blink::WebVector<int> ends; | |
| 467 inline_text_box.wordBoundaries(starts, ends); | |
| 468 size_t word_count = starts.size(); | |
| 469 DCHECK_EQ(ends.size(), word_count); | |
| 470 | |
| 471 // If there are no words, use the InlineTextBox boundaries. | |
| 472 if (!word_count) { | |
| 473 word_start = start; | |
| 474 word_end = end; | |
| 475 return; | |
| 476 } | |
| 477 | |
| 478 // Look for a character within any word other than the last. | |
| 479 for (size_t j = 0; j < word_count - 1; j++) { | |
| 480 if (localIndex <= ends[j]) { | |
| 481 word_start = start + starts[j]; | |
| 482 word_end = start + ends[j]; | |
| 483 return; | |
| 484 } | |
| 485 } | |
| 486 | |
| 487 // Return the last word by default. | |
| 488 word_start = start + starts[word_count - 1]; | |
| 489 word_end = start + ends[word_count - 1]; | |
| 490 return; | |
| 491 } | |
| 492 } | |
| 493 | |
| 494 // Collects attributes into a string, delimited by dashes. Used by all methods | |
| 495 // that output lists of attributes: attributesOfLinkedUIElementsCallback, | |
| 496 // AttributesOfChildrenCallback, etc. | |
| 497 class AttributesCollector { | |
| 498 public: | |
| 499 AttributesCollector() {} | |
| 500 ~AttributesCollector() {} | |
| 501 | |
| 502 void CollectAttributes(const blink::WebAXObject& object) { | |
| 503 attributes_.append("\n------------\n"); | |
| 504 attributes_.append(GetAttributes(object)); | |
| 505 } | |
| 506 | |
| 507 std::string attributes() const { return attributes_; } | |
| 508 | |
| 509 private: | |
| 510 std::string attributes_; | |
| 511 | |
| 512 DISALLOW_COPY_AND_ASSIGN(AttributesCollector); | |
| 513 }; | |
| 514 | |
| 515 class SparseAttributeAdapter : public blink::WebAXSparseAttributeClient { | |
| 516 public: | |
| 517 SparseAttributeAdapter() {} | |
| 518 ~SparseAttributeAdapter() override {} | |
| 519 | |
| 520 std::map<blink::WebAXBoolAttribute, bool> bool_attributes; | |
| 521 std::map<blink::WebAXStringAttribute, blink::WebString> string_attributes; | |
| 522 std::map<blink::WebAXObjectAttribute, blink::WebAXObject> object_attributes; | |
| 523 std::map<blink::WebAXObjectVectorAttribute, | |
| 524 blink::WebVector<blink::WebAXObject>> | |
| 525 object_vector_attributes; | |
| 526 | |
| 527 private: | |
| 528 void addBoolAttribute(blink::WebAXBoolAttribute attribute, | |
| 529 bool value) override { | |
| 530 bool_attributes[attribute] = value; | |
| 531 } | |
| 532 | |
| 533 void addStringAttribute(blink::WebAXStringAttribute attribute, | |
| 534 const blink::WebString& value) override { | |
| 535 string_attributes[attribute] = value; | |
| 536 } | |
| 537 | |
| 538 void addObjectAttribute(blink::WebAXObjectAttribute attribute, | |
| 539 const blink::WebAXObject& value) override { | |
| 540 object_attributes[attribute] = value; | |
| 541 } | |
| 542 | |
| 543 void addObjectVectorAttribute( | |
| 544 blink::WebAXObjectVectorAttribute attribute, | |
| 545 const blink::WebVector<blink::WebAXObject>& value) override { | |
| 546 object_vector_attributes[attribute] = value; | |
| 547 } | |
| 548 }; | |
| 549 | |
| 550 } // namespace | |
| 551 | |
| 552 gin::WrapperInfo WebAXObjectProxy::kWrapperInfo = { | |
| 553 gin::kEmbedderNativeGin}; | |
| 554 | |
| 555 WebAXObjectProxy::WebAXObjectProxy(const blink::WebAXObject& object, | |
| 556 WebAXObjectProxy::Factory* factory) | |
| 557 : accessibility_object_(object), | |
| 558 factory_(factory) { | |
| 559 } | |
| 560 | |
| 561 WebAXObjectProxy::~WebAXObjectProxy() {} | |
| 562 | |
| 563 gin::ObjectTemplateBuilder | |
| 564 WebAXObjectProxy::GetObjectTemplateBuilder(v8::Isolate* isolate) { | |
| 565 return gin::Wrappable<WebAXObjectProxy>::GetObjectTemplateBuilder(isolate) | |
| 566 .SetProperty("role", &WebAXObjectProxy::Role) | |
| 567 .SetProperty("stringValue", &WebAXObjectProxy::StringValue) | |
| 568 .SetProperty("language", &WebAXObjectProxy::Language) | |
| 569 .SetProperty("x", &WebAXObjectProxy::X) | |
| 570 .SetProperty("y", &WebAXObjectProxy::Y) | |
| 571 .SetProperty("width", &WebAXObjectProxy::Width) | |
| 572 .SetProperty("height", &WebAXObjectProxy::Height) | |
| 573 .SetProperty("intValue", &WebAXObjectProxy::IntValue) | |
| 574 .SetProperty("minValue", &WebAXObjectProxy::MinValue) | |
| 575 .SetProperty("maxValue", &WebAXObjectProxy::MaxValue) | |
| 576 .SetProperty("valueDescription", &WebAXObjectProxy::ValueDescription) | |
| 577 .SetProperty("childrenCount", &WebAXObjectProxy::ChildrenCount) | |
| 578 .SetProperty("selectionAnchorObject", | |
| 579 &WebAXObjectProxy::SelectionAnchorObject) | |
| 580 .SetProperty("selectionAnchorOffset", | |
| 581 &WebAXObjectProxy::SelectionAnchorOffset) | |
| 582 .SetProperty("selectionAnchorAffinity", | |
| 583 &WebAXObjectProxy::SelectionAnchorAffinity) | |
| 584 .SetProperty("selectionFocusObject", | |
| 585 &WebAXObjectProxy::SelectionFocusObject) | |
| 586 .SetProperty("selectionFocusOffset", | |
| 587 &WebAXObjectProxy::SelectionFocusOffset) | |
| 588 .SetProperty("selectionFocusAffinity", | |
| 589 &WebAXObjectProxy::SelectionFocusAffinity) | |
| 590 .SetProperty("selectionStart", &WebAXObjectProxy::SelectionStart) | |
| 591 .SetProperty("selectionEnd", &WebAXObjectProxy::SelectionEnd) | |
| 592 .SetProperty("selectionStartLineNumber", | |
| 593 &WebAXObjectProxy::SelectionStartLineNumber) | |
| 594 .SetProperty("selectionEndLineNumber", | |
| 595 &WebAXObjectProxy::SelectionEndLineNumber) | |
| 596 .SetProperty("isEnabled", &WebAXObjectProxy::IsEnabled) | |
| 597 .SetProperty("isRequired", &WebAXObjectProxy::IsRequired) | |
| 598 .SetProperty("isEditable", &WebAXObjectProxy::IsEditable) | |
| 599 .SetProperty("isRichlyEditable", &WebAXObjectProxy::IsRichlyEditable) | |
| 600 .SetProperty("isFocused", &WebAXObjectProxy::IsFocused) | |
| 601 .SetProperty("isFocusable", &WebAXObjectProxy::IsFocusable) | |
| 602 .SetProperty("isModal", &WebAXObjectProxy::IsModal) | |
| 603 .SetProperty("isSelected", &WebAXObjectProxy::IsSelected) | |
| 604 .SetProperty("isSelectable", &WebAXObjectProxy::IsSelectable) | |
| 605 .SetProperty("isMultiSelectable", &WebAXObjectProxy::IsMultiSelectable) | |
| 606 .SetProperty("isSelectedOptionActive", | |
| 607 &WebAXObjectProxy::IsSelectedOptionActive) | |
| 608 .SetProperty("isExpanded", &WebAXObjectProxy::IsExpanded) | |
| 609 .SetProperty("isChecked", &WebAXObjectProxy::IsChecked) | |
| 610 .SetProperty("isVisible", &WebAXObjectProxy::IsVisible) | |
| 611 .SetProperty("isOffScreen", &WebAXObjectProxy::IsOffScreen) | |
| 612 .SetProperty("isCollapsed", &WebAXObjectProxy::IsCollapsed) | |
| 613 .SetProperty("hasPopup", &WebAXObjectProxy::HasPopup) | |
| 614 .SetProperty("isValid", &WebAXObjectProxy::IsValid) | |
| 615 .SetProperty("isReadOnly", &WebAXObjectProxy::IsReadOnly) | |
| 616 .SetProperty("backgroundColor", &WebAXObjectProxy::BackgroundColor) | |
| 617 .SetProperty("color", &WebAXObjectProxy::Color) | |
| 618 .SetProperty("colorValue", &WebAXObjectProxy::ColorValue) | |
| 619 .SetProperty("fontFamily", &WebAXObjectProxy::FontFamily) | |
| 620 .SetProperty("fontSize", &WebAXObjectProxy::FontSize) | |
| 621 .SetProperty("orientation", &WebAXObjectProxy::Orientation) | |
| 622 .SetProperty("posInSet", &WebAXObjectProxy::PosInSet) | |
| 623 .SetProperty("setSize", &WebAXObjectProxy::SetSize) | |
| 624 .SetProperty("clickPointX", &WebAXObjectProxy::ClickPointX) | |
| 625 .SetProperty("clickPointY", &WebAXObjectProxy::ClickPointY) | |
| 626 .SetProperty("rowCount", &WebAXObjectProxy::RowCount) | |
| 627 .SetProperty("rowHeadersCount", &WebAXObjectProxy::RowHeadersCount) | |
| 628 .SetProperty("columnCount", &WebAXObjectProxy::ColumnCount) | |
| 629 .SetProperty("columnHeadersCount", &WebAXObjectProxy::ColumnHeadersCount) | |
| 630 .SetProperty("isClickable", &WebAXObjectProxy::IsClickable) | |
| 631 .SetProperty("isButtonStateMixed", &WebAXObjectProxy::IsButtonStateMixed) | |
| 632 // | |
| 633 // NEW bounding rect calculation - high-level interface | |
| 634 // | |
| 635 .SetProperty("boundsX", &WebAXObjectProxy::BoundsX) | |
| 636 .SetProperty("boundsY", &WebAXObjectProxy::BoundsY) | |
| 637 .SetProperty("boundsWidth", &WebAXObjectProxy::BoundsWidth) | |
| 638 .SetProperty("boundsHeight", &WebAXObjectProxy::BoundsHeight) | |
| 639 .SetMethod("allAttributes", &WebAXObjectProxy::AllAttributes) | |
| 640 .SetMethod("attributesOfChildren", | |
| 641 &WebAXObjectProxy::AttributesOfChildren) | |
| 642 .SetMethod("ariaControlsElementAtIndex", | |
| 643 &WebAXObjectProxy::AriaControlsElementAtIndex) | |
| 644 .SetMethod("ariaFlowToElementAtIndex", | |
| 645 &WebAXObjectProxy::AriaFlowToElementAtIndex) | |
| 646 .SetMethod("ariaOwnsElementAtIndex", | |
| 647 &WebAXObjectProxy::AriaOwnsElementAtIndex) | |
| 648 .SetMethod("lineForIndex", &WebAXObjectProxy::LineForIndex) | |
| 649 .SetMethod("boundsForRange", &WebAXObjectProxy::BoundsForRange) | |
| 650 .SetMethod("childAtIndex", &WebAXObjectProxy::ChildAtIndex) | |
| 651 .SetMethod("elementAtPoint", &WebAXObjectProxy::ElementAtPoint) | |
| 652 .SetMethod("tableHeader", &WebAXObjectProxy::TableHeader) | |
| 653 .SetMethod("rowHeaderAtIndex", &WebAXObjectProxy::RowHeaderAtIndex) | |
| 654 .SetMethod("columnHeaderAtIndex", &WebAXObjectProxy::ColumnHeaderAtIndex) | |
| 655 .SetMethod("rowIndexRange", &WebAXObjectProxy::RowIndexRange) | |
| 656 .SetMethod("columnIndexRange", &WebAXObjectProxy::ColumnIndexRange) | |
| 657 .SetMethod("cellForColumnAndRow", &WebAXObjectProxy::CellForColumnAndRow) | |
| 658 .SetMethod("setSelectedTextRange", | |
| 659 &WebAXObjectProxy::SetSelectedTextRange) | |
| 660 .SetMethod("setSelection", &WebAXObjectProxy::SetSelection) | |
| 661 .SetMethod("isAttributeSettable", &WebAXObjectProxy::IsAttributeSettable) | |
| 662 .SetMethod("isPressActionSupported", | |
| 663 &WebAXObjectProxy::IsPressActionSupported) | |
| 664 .SetMethod("isIncrementActionSupported", | |
| 665 &WebAXObjectProxy::IsIncrementActionSupported) | |
| 666 .SetMethod("isDecrementActionSupported", | |
| 667 &WebAXObjectProxy::IsDecrementActionSupported) | |
| 668 .SetMethod("parentElement", &WebAXObjectProxy::ParentElement) | |
| 669 .SetMethod("increment", &WebAXObjectProxy::Increment) | |
| 670 .SetMethod("decrement", &WebAXObjectProxy::Decrement) | |
| 671 .SetMethod("showMenu", &WebAXObjectProxy::ShowMenu) | |
| 672 .SetMethod("press", &WebAXObjectProxy::Press) | |
| 673 .SetMethod("setValue", &WebAXObjectProxy::SetValue) | |
| 674 .SetMethod("isEqual", &WebAXObjectProxy::IsEqual) | |
| 675 .SetMethod("setNotificationListener", | |
| 676 &WebAXObjectProxy::SetNotificationListener) | |
| 677 .SetMethod("unsetNotificationListener", | |
| 678 &WebAXObjectProxy::UnsetNotificationListener) | |
| 679 .SetMethod("takeFocus", &WebAXObjectProxy::TakeFocus) | |
| 680 .SetMethod("scrollToMakeVisible", &WebAXObjectProxy::ScrollToMakeVisible) | |
| 681 .SetMethod("scrollToMakeVisibleWithSubFocus", | |
| 682 &WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus) | |
| 683 .SetMethod("scrollToGlobalPoint", &WebAXObjectProxy::ScrollToGlobalPoint) | |
| 684 .SetMethod("scrollX", &WebAXObjectProxy::ScrollX) | |
| 685 .SetMethod("scrollY", &WebAXObjectProxy::ScrollY) | |
| 686 .SetMethod("wordStart", &WebAXObjectProxy::WordStart) | |
| 687 .SetMethod("wordEnd", &WebAXObjectProxy::WordEnd) | |
| 688 .SetMethod("nextOnLine", &WebAXObjectProxy::NextOnLine) | |
| 689 .SetMethod("previousOnLine", &WebAXObjectProxy::PreviousOnLine) | |
| 690 .SetMethod("misspellingAtIndex", &WebAXObjectProxy::MisspellingAtIndex) | |
| 691 // TODO(hajimehoshi): This is for backward compatibility. Remove them. | |
| 692 .SetMethod("addNotificationListener", | |
| 693 &WebAXObjectProxy::SetNotificationListener) | |
| 694 .SetMethod("removeNotificationListener", | |
| 695 &WebAXObjectProxy::UnsetNotificationListener) | |
| 696 // | |
| 697 // NEW accessible name and description accessors | |
| 698 // | |
| 699 .SetProperty("name", &WebAXObjectProxy::Name) | |
| 700 .SetProperty("nameFrom", &WebAXObjectProxy::NameFrom) | |
| 701 .SetMethod("nameElementCount", &WebAXObjectProxy::NameElementCount) | |
| 702 .SetMethod("nameElementAtIndex", &WebAXObjectProxy::NameElementAtIndex) | |
| 703 .SetProperty("description", &WebAXObjectProxy::Description) | |
| 704 .SetProperty("descriptionFrom", &WebAXObjectProxy::DescriptionFrom) | |
| 705 .SetProperty("placeholder", &WebAXObjectProxy::Placeholder) | |
| 706 .SetProperty("misspellingsCount", &WebAXObjectProxy::MisspellingsCount) | |
| 707 .SetMethod("descriptionElementCount", | |
| 708 &WebAXObjectProxy::DescriptionElementCount) | |
| 709 .SetMethod("descriptionElementAtIndex", | |
| 710 &WebAXObjectProxy::DescriptionElementAtIndex) | |
| 711 // | |
| 712 // NEW bounding rect calculation - low-level interface | |
| 713 // | |
| 714 .SetMethod("offsetContainer", &WebAXObjectProxy::OffsetContainer) | |
| 715 .SetMethod("boundsInContainerX", &WebAXObjectProxy::BoundsInContainerX) | |
| 716 .SetMethod("boundsInContainerY", &WebAXObjectProxy::BoundsInContainerY) | |
| 717 .SetMethod("boundsInContainerWidth", | |
| 718 &WebAXObjectProxy::BoundsInContainerWidth) | |
| 719 .SetMethod("boundsInContainerHeight", | |
| 720 &WebAXObjectProxy::BoundsInContainerHeight) | |
| 721 .SetMethod("hasNonIdentityTransform", | |
| 722 &WebAXObjectProxy::HasNonIdentityTransform); | |
| 723 } | |
| 724 | |
| 725 v8::Local<v8::Object> WebAXObjectProxy::GetChildAtIndex(unsigned index) { | |
| 726 return factory_->GetOrCreate(accessibility_object_.childAt(index)); | |
| 727 } | |
| 728 | |
| 729 bool WebAXObjectProxy::IsRoot() const { | |
| 730 return false; | |
| 731 } | |
| 732 | |
| 733 bool WebAXObjectProxy::IsEqualToObject(const blink::WebAXObject& other) { | |
| 734 return accessibility_object_.equals(other); | |
| 735 } | |
| 736 | |
| 737 void WebAXObjectProxy::NotificationReceived( | |
| 738 blink::WebFrame* frame, | |
| 739 const std::string& notification_name) { | |
| 740 if (notification_callback_.IsEmpty()) | |
| 741 return; | |
| 742 | |
| 743 v8::Local<v8::Context> context = frame->mainWorldScriptContext(); | |
| 744 if (context.IsEmpty()) | |
| 745 return; | |
| 746 | |
| 747 v8::Isolate* isolate = blink::mainThreadIsolate(); | |
| 748 | |
| 749 v8::Local<v8::Value> argv[] = { | |
| 750 v8::String::NewFromUtf8(isolate, notification_name.data(), | |
| 751 v8::String::kNormalString, | |
| 752 notification_name.size()), | |
| 753 }; | |
| 754 frame->callFunctionEvenIfScriptDisabled( | |
| 755 v8::Local<v8::Function>::New(isolate, notification_callback_), | |
| 756 context->Global(), | |
| 757 arraysize(argv), | |
| 758 argv); | |
| 759 } | |
| 760 | |
| 761 void WebAXObjectProxy::Reset() { | |
| 762 notification_callback_.Reset(); | |
| 763 } | |
| 764 | |
| 765 std::string WebAXObjectProxy::Role() { | |
| 766 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 767 return GetRole(accessibility_object_); | |
| 768 } | |
| 769 | |
| 770 std::string WebAXObjectProxy::StringValue() { | |
| 771 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 772 return GetStringValue(accessibility_object_); | |
| 773 } | |
| 774 | |
| 775 std::string WebAXObjectProxy::Language() { | |
| 776 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 777 return GetLanguage(accessibility_object_); | |
| 778 } | |
| 779 | |
| 780 int WebAXObjectProxy::X() { | |
| 781 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 782 return BoundsForObject(accessibility_object_).x; | |
| 783 } | |
| 784 | |
| 785 int WebAXObjectProxy::Y() { | |
| 786 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 787 return BoundsForObject(accessibility_object_).y; | |
| 788 } | |
| 789 | |
| 790 int WebAXObjectProxy::Width() { | |
| 791 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 792 return BoundsForObject(accessibility_object_).width; | |
| 793 } | |
| 794 | |
| 795 int WebAXObjectProxy::Height() { | |
| 796 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 797 return BoundsForObject(accessibility_object_).height; | |
| 798 } | |
| 799 | |
| 800 int WebAXObjectProxy::IntValue() { | |
| 801 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 802 if (accessibility_object_.supportsRangeValue()) | |
| 803 return accessibility_object_.valueForRange(); | |
| 804 else if (accessibility_object_.role() == blink::WebAXRoleHeading) | |
| 805 return accessibility_object_.headingLevel(); | |
| 806 else | |
| 807 return atoi(accessibility_object_.stringValue().utf8().data()); | |
| 808 } | |
| 809 | |
| 810 int WebAXObjectProxy::MinValue() { | |
| 811 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 812 return accessibility_object_.minValueForRange(); | |
| 813 } | |
| 814 | |
| 815 int WebAXObjectProxy::MaxValue() { | |
| 816 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 817 return accessibility_object_.maxValueForRange(); | |
| 818 } | |
| 819 | |
| 820 std::string WebAXObjectProxy::ValueDescription() { | |
| 821 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 822 return GetValueDescription(accessibility_object_); | |
| 823 } | |
| 824 | |
| 825 int WebAXObjectProxy::ChildrenCount() { | |
| 826 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 827 int count = 1; // Root object always has only one child, the WebView. | |
| 828 if (!IsRoot()) | |
| 829 count = accessibility_object_.childCount(); | |
| 830 return count; | |
| 831 } | |
| 832 | |
| 833 v8::Local<v8::Value> WebAXObjectProxy::SelectionAnchorObject() { | |
| 834 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 835 | |
| 836 blink::WebAXObject anchorObject; | |
| 837 int anchorOffset = -1; | |
| 838 blink::WebAXTextAffinity anchorAffinity; | |
| 839 blink::WebAXObject focusObject; | |
| 840 int focusOffset = -1; | |
| 841 blink::WebAXTextAffinity focusAffinity; | |
| 842 accessibility_object_.selection(anchorObject, anchorOffset, anchorAffinity, | |
| 843 focusObject, focusOffset, focusAffinity); | |
| 844 if (anchorObject.isNull()) | |
| 845 return v8::Null(blink::mainThreadIsolate()); | |
| 846 | |
| 847 return factory_->GetOrCreate(anchorObject); | |
| 848 } | |
| 849 | |
| 850 int WebAXObjectProxy::SelectionAnchorOffset() { | |
| 851 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 852 | |
| 853 blink::WebAXObject anchorObject; | |
| 854 int anchorOffset = -1; | |
| 855 blink::WebAXTextAffinity anchorAffinity; | |
| 856 blink::WebAXObject focusObject; | |
| 857 int focusOffset = -1; | |
| 858 blink::WebAXTextAffinity focusAffinity; | |
| 859 accessibility_object_.selection(anchorObject, anchorOffset, anchorAffinity, | |
| 860 focusObject, focusOffset, focusAffinity); | |
| 861 if (anchorOffset < 0) | |
| 862 return -1; | |
| 863 | |
| 864 return anchorOffset; | |
| 865 } | |
| 866 | |
| 867 std::string WebAXObjectProxy::SelectionAnchorAffinity() { | |
| 868 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 869 | |
| 870 blink::WebAXObject anchorObject; | |
| 871 int anchorOffset = -1; | |
| 872 blink::WebAXTextAffinity anchorAffinity; | |
| 873 blink::WebAXObject focusObject; | |
| 874 int focusOffset = -1; | |
| 875 blink::WebAXTextAffinity focusAffinity; | |
| 876 accessibility_object_.selection(anchorObject, anchorOffset, anchorAffinity, | |
| 877 focusObject, focusOffset, focusAffinity); | |
| 878 return anchorAffinity == blink::WebAXTextAffinityUpstream ? | |
| 879 "upstream" : "downstream"; | |
| 880 } | |
| 881 | |
| 882 v8::Local<v8::Value> WebAXObjectProxy::SelectionFocusObject() { | |
| 883 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 884 | |
| 885 blink::WebAXObject anchorObject; | |
| 886 int anchorOffset = -1; | |
| 887 blink::WebAXTextAffinity anchorAffinity; | |
| 888 blink::WebAXObject focusObject; | |
| 889 int focusOffset = -1; | |
| 890 blink::WebAXTextAffinity focusAffinity; | |
| 891 accessibility_object_.selection(anchorObject, anchorOffset, anchorAffinity, | |
| 892 focusObject, focusOffset, focusAffinity); | |
| 893 if (focusObject.isNull()) | |
| 894 return v8::Null(blink::mainThreadIsolate()); | |
| 895 | |
| 896 return factory_->GetOrCreate(focusObject); | |
| 897 } | |
| 898 | |
| 899 int WebAXObjectProxy::SelectionFocusOffset() { | |
| 900 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 901 | |
| 902 blink::WebAXObject anchorObject; | |
| 903 int anchorOffset = -1; | |
| 904 blink::WebAXTextAffinity anchorAffinity; | |
| 905 blink::WebAXObject focusObject; | |
| 906 int focusOffset = -1; | |
| 907 blink::WebAXTextAffinity focusAffinity; | |
| 908 accessibility_object_.selection(anchorObject, anchorOffset, anchorAffinity, | |
| 909 focusObject, focusOffset, focusAffinity); | |
| 910 if (focusOffset < 0) | |
| 911 return -1; | |
| 912 | |
| 913 return focusOffset; | |
| 914 } | |
| 915 | |
| 916 std::string WebAXObjectProxy::SelectionFocusAffinity() { | |
| 917 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 918 | |
| 919 blink::WebAXObject anchorObject; | |
| 920 int anchorOffset = -1; | |
| 921 blink::WebAXTextAffinity anchorAffinity; | |
| 922 blink::WebAXObject focusObject; | |
| 923 int focusOffset = -1; | |
| 924 blink::WebAXTextAffinity focusAffinity; | |
| 925 accessibility_object_.selection(anchorObject, anchorOffset, anchorAffinity, | |
| 926 focusObject, focusOffset, focusAffinity); | |
| 927 return focusAffinity == blink::WebAXTextAffinityUpstream ? | |
| 928 "upstream" : "downstream"; | |
| 929 } | |
| 930 | |
| 931 int WebAXObjectProxy::SelectionStart() { | |
| 932 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 933 return accessibility_object_.selectionStart(); | |
| 934 } | |
| 935 | |
| 936 int WebAXObjectProxy::SelectionEnd() { | |
| 937 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 938 return accessibility_object_.selectionEnd(); | |
| 939 } | |
| 940 | |
| 941 int WebAXObjectProxy::SelectionStartLineNumber() { | |
| 942 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 943 return accessibility_object_.selectionStartLineNumber(); | |
| 944 } | |
| 945 | |
| 946 int WebAXObjectProxy::SelectionEndLineNumber() { | |
| 947 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 948 return accessibility_object_.selectionEndLineNumber(); | |
| 949 } | |
| 950 | |
| 951 bool WebAXObjectProxy::IsEnabled() { | |
| 952 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 953 return accessibility_object_.isEnabled(); | |
| 954 } | |
| 955 | |
| 956 bool WebAXObjectProxy::IsRequired() { | |
| 957 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 958 return accessibility_object_.isRequired(); | |
| 959 } | |
| 960 | |
| 961 bool WebAXObjectProxy::IsEditable() { | |
| 962 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 963 return accessibility_object_.isEditable(); | |
| 964 } | |
| 965 | |
| 966 bool WebAXObjectProxy::IsRichlyEditable() { | |
| 967 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 968 return accessibility_object_.isRichlyEditable(); | |
| 969 } | |
| 970 | |
| 971 bool WebAXObjectProxy::IsFocused() { | |
| 972 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 973 return accessibility_object_.isFocused(); | |
| 974 } | |
| 975 | |
| 976 bool WebAXObjectProxy::IsFocusable() { | |
| 977 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 978 return accessibility_object_.canSetFocusAttribute(); | |
| 979 } | |
| 980 | |
| 981 bool WebAXObjectProxy::IsModal() { | |
| 982 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 983 return accessibility_object_.isModal(); | |
| 984 } | |
| 985 | |
| 986 bool WebAXObjectProxy::IsSelected() { | |
| 987 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 988 return accessibility_object_.isSelected(); | |
| 989 } | |
| 990 | |
| 991 bool WebAXObjectProxy::IsSelectable() { | |
| 992 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 993 return accessibility_object_.canSetSelectedAttribute(); | |
| 994 } | |
| 995 | |
| 996 bool WebAXObjectProxy::IsMultiSelectable() { | |
| 997 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 998 return accessibility_object_.isMultiSelectable(); | |
| 999 } | |
| 1000 | |
| 1001 bool WebAXObjectProxy::IsSelectedOptionActive() { | |
| 1002 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1003 return accessibility_object_.isSelectedOptionActive(); | |
| 1004 } | |
| 1005 | |
| 1006 bool WebAXObjectProxy::IsExpanded() { | |
| 1007 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1008 return accessibility_object_.isExpanded() == blink::WebAXExpandedExpanded; | |
| 1009 } | |
| 1010 | |
| 1011 bool WebAXObjectProxy::IsChecked() { | |
| 1012 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1013 return accessibility_object_.isChecked(); | |
| 1014 } | |
| 1015 | |
| 1016 bool WebAXObjectProxy::IsCollapsed() { | |
| 1017 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1018 return accessibility_object_.isExpanded() == blink::WebAXExpandedCollapsed; | |
| 1019 } | |
| 1020 | |
| 1021 bool WebAXObjectProxy::IsVisible() { | |
| 1022 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1023 return accessibility_object_.isVisible(); | |
| 1024 } | |
| 1025 | |
| 1026 bool WebAXObjectProxy::IsOffScreen() { | |
| 1027 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1028 return accessibility_object_.isOffScreen(); | |
| 1029 } | |
| 1030 | |
| 1031 bool WebAXObjectProxy::HasPopup() { | |
| 1032 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1033 return accessibility_object_.ariaHasPopup(); | |
| 1034 } | |
| 1035 | |
| 1036 bool WebAXObjectProxy::IsValid() { | |
| 1037 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1038 return !accessibility_object_.isDetached(); | |
| 1039 } | |
| 1040 | |
| 1041 bool WebAXObjectProxy::IsReadOnly() { | |
| 1042 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1043 return accessibility_object_.isReadOnly(); | |
| 1044 } | |
| 1045 | |
| 1046 unsigned int WebAXObjectProxy::BackgroundColor() { | |
| 1047 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1048 return accessibility_object_.backgroundColor(); | |
| 1049 } | |
| 1050 | |
| 1051 unsigned int WebAXObjectProxy::Color() { | |
| 1052 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1053 unsigned int color = accessibility_object_.color(); | |
| 1054 // Remove the alpha because it's always 1 and thus not informative. | |
| 1055 return color & 0xFFFFFF; | |
| 1056 } | |
| 1057 | |
| 1058 // For input elements of type color. | |
| 1059 unsigned int WebAXObjectProxy::ColorValue() { | |
| 1060 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1061 return accessibility_object_.colorValue(); | |
| 1062 } | |
| 1063 | |
| 1064 std::string WebAXObjectProxy::FontFamily() { | |
| 1065 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1066 std::string font_family(accessibility_object_.fontFamily().utf8()); | |
| 1067 return font_family.insert(0, "AXFontFamily: "); | |
| 1068 } | |
| 1069 | |
| 1070 float WebAXObjectProxy::FontSize() { | |
| 1071 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1072 return accessibility_object_.fontSize(); | |
| 1073 } | |
| 1074 | |
| 1075 std::string WebAXObjectProxy::Orientation() { | |
| 1076 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1077 if (accessibility_object_.orientation() == blink::WebAXOrientationVertical) | |
| 1078 return "AXOrientation: AXVerticalOrientation"; | |
| 1079 else if (accessibility_object_.orientation() | |
| 1080 == blink::WebAXOrientationHorizontal) | |
| 1081 return "AXOrientation: AXHorizontalOrientation"; | |
| 1082 | |
| 1083 return std::string(); | |
| 1084 } | |
| 1085 | |
| 1086 int WebAXObjectProxy::PosInSet() { | |
| 1087 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1088 return accessibility_object_.posInSet(); | |
| 1089 } | |
| 1090 | |
| 1091 int WebAXObjectProxy::SetSize() { | |
| 1092 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1093 return accessibility_object_.setSize(); | |
| 1094 } | |
| 1095 | |
| 1096 int WebAXObjectProxy::ClickPointX() { | |
| 1097 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1098 blink::WebFloatRect bounds = BoundsForObject(accessibility_object_); | |
| 1099 return bounds.x + bounds.width / 2; | |
| 1100 } | |
| 1101 | |
| 1102 int WebAXObjectProxy::ClickPointY() { | |
| 1103 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1104 blink::WebFloatRect bounds = BoundsForObject(accessibility_object_); | |
| 1105 return bounds.y + bounds.height / 2; | |
| 1106 } | |
| 1107 | |
| 1108 int32_t WebAXObjectProxy::RowCount() { | |
| 1109 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1110 return static_cast<int32_t>(accessibility_object_.rowCount()); | |
| 1111 } | |
| 1112 | |
| 1113 int32_t WebAXObjectProxy::RowHeadersCount() { | |
| 1114 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1115 blink::WebVector<blink::WebAXObject> headers; | |
| 1116 accessibility_object_.rowHeaders(headers); | |
| 1117 return static_cast<int32_t>(headers.size()); | |
| 1118 } | |
| 1119 | |
| 1120 int32_t WebAXObjectProxy::ColumnCount() { | |
| 1121 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1122 return static_cast<int32_t>(accessibility_object_.columnCount()); | |
| 1123 } | |
| 1124 | |
| 1125 int32_t WebAXObjectProxy::ColumnHeadersCount() | |
| 1126 { | |
| 1127 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1128 blink::WebVector<blink::WebAXObject> headers; | |
| 1129 accessibility_object_.columnHeaders(headers); | |
| 1130 return static_cast<int32_t>(headers.size()); | |
| 1131 } | |
| 1132 | |
| 1133 bool WebAXObjectProxy::IsClickable() { | |
| 1134 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1135 return accessibility_object_.isClickable(); | |
| 1136 } | |
| 1137 | |
| 1138 bool WebAXObjectProxy::IsButtonStateMixed() { | |
| 1139 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1140 return accessibility_object_.isButtonStateMixed(); | |
| 1141 } | |
| 1142 | |
| 1143 v8::Local<v8::Object> WebAXObjectProxy::AriaControlsElementAtIndex( | |
| 1144 unsigned index) { | |
| 1145 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1146 SparseAttributeAdapter attribute_adapter; | |
| 1147 accessibility_object_.getSparseAXAttributes(attribute_adapter); | |
| 1148 blink::WebVector<blink::WebAXObject> elements = | |
| 1149 attribute_adapter.object_vector_attributes | |
| 1150 [blink::WebAXObjectVectorAttribute::AriaControls]; | |
| 1151 size_t elementCount = elements.size(); | |
| 1152 if (index >= elementCount) | |
| 1153 return v8::Local<v8::Object>(); | |
| 1154 | |
| 1155 return factory_->GetOrCreate(elements[index]); | |
| 1156 } | |
| 1157 | |
| 1158 v8::Local<v8::Object> WebAXObjectProxy::AriaFlowToElementAtIndex( | |
| 1159 unsigned index) { | |
| 1160 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1161 SparseAttributeAdapter attribute_adapter; | |
| 1162 accessibility_object_.getSparseAXAttributes(attribute_adapter); | |
| 1163 blink::WebVector<blink::WebAXObject> elements = | |
| 1164 attribute_adapter.object_vector_attributes | |
| 1165 [blink::WebAXObjectVectorAttribute::AriaFlowTo]; | |
| 1166 size_t elementCount = elements.size(); | |
| 1167 if (index >= elementCount) | |
| 1168 return v8::Local<v8::Object>(); | |
| 1169 | |
| 1170 return factory_->GetOrCreate(elements[index]); | |
| 1171 } | |
| 1172 | |
| 1173 v8::Local<v8::Object> WebAXObjectProxy::AriaOwnsElementAtIndex(unsigned index) | |
| 1174 { | |
| 1175 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1176 blink::WebVector<blink::WebAXObject> elements; | |
| 1177 accessibility_object_.ariaOwns(elements); | |
| 1178 size_t elementCount = elements.size(); | |
| 1179 if (index >= elementCount) | |
| 1180 return v8::Local<v8::Object>(); | |
| 1181 | |
| 1182 return factory_->GetOrCreate(elements[index]); | |
| 1183 } | |
| 1184 | |
| 1185 std::string WebAXObjectProxy::AllAttributes() { | |
| 1186 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1187 return GetAttributes(accessibility_object_); | |
| 1188 } | |
| 1189 | |
| 1190 std::string WebAXObjectProxy::AttributesOfChildren() { | |
| 1191 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1192 AttributesCollector collector; | |
| 1193 unsigned size = accessibility_object_.childCount(); | |
| 1194 for (unsigned i = 0; i < size; ++i) | |
| 1195 collector.CollectAttributes(accessibility_object_.childAt(i)); | |
| 1196 return collector.attributes(); | |
| 1197 } | |
| 1198 | |
| 1199 int WebAXObjectProxy::LineForIndex(int index) { | |
| 1200 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1201 blink::WebVector<int> line_breaks; | |
| 1202 accessibility_object_.lineBreaks(line_breaks); | |
| 1203 int line = 0; | |
| 1204 int vector_size = static_cast<int>(line_breaks.size()); | |
| 1205 while (line < vector_size && line_breaks[line] <= index) | |
| 1206 line++; | |
| 1207 return line; | |
| 1208 } | |
| 1209 | |
| 1210 std::string WebAXObjectProxy::BoundsForRange(int start, int end) { | |
| 1211 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1212 if (accessibility_object_.role() != blink::WebAXRoleStaticText) | |
| 1213 return std::string(); | |
| 1214 | |
| 1215 if (!accessibility_object_.updateLayoutAndCheckValidity()) | |
| 1216 return std::string(); | |
| 1217 | |
| 1218 int len = end - start; | |
| 1219 | |
| 1220 // Get the bounds for each character and union them into one large rectangle. | |
| 1221 // This is just for testing so it doesn't need to be efficient. | |
| 1222 blink::WebRect bounds = BoundsForCharacter(accessibility_object_, start); | |
| 1223 for (int i = 1; i < len; i++) { | |
| 1224 blink::WebRect next = BoundsForCharacter(accessibility_object_, start + i); | |
| 1225 int right = std::max(bounds.x + bounds.width, next.x + next.width); | |
| 1226 int bottom = std::max(bounds.y + bounds.height, next.y + next.height); | |
| 1227 bounds.x = std::min(bounds.x, next.x); | |
| 1228 bounds.y = std::min(bounds.y, next.y); | |
| 1229 bounds.width = right - bounds.x; | |
| 1230 bounds.height = bottom - bounds.y; | |
| 1231 } | |
| 1232 | |
| 1233 return base::StringPrintf("{x: %d, y: %d, width: %d, height: %d}", | |
| 1234 bounds.x, bounds.y, bounds.width, bounds.height); | |
| 1235 } | |
| 1236 | |
| 1237 v8::Local<v8::Object> WebAXObjectProxy::ChildAtIndex(int index) { | |
| 1238 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1239 return GetChildAtIndex(index); | |
| 1240 } | |
| 1241 | |
| 1242 v8::Local<v8::Object> WebAXObjectProxy::ElementAtPoint(int x, int y) { | |
| 1243 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1244 blink::WebPoint point(x, y); | |
| 1245 blink::WebAXObject obj = accessibility_object_.hitTest(point); | |
| 1246 if (obj.isNull()) | |
| 1247 return v8::Local<v8::Object>(); | |
| 1248 | |
| 1249 return factory_->GetOrCreate(obj); | |
| 1250 } | |
| 1251 | |
| 1252 v8::Local<v8::Object> WebAXObjectProxy::TableHeader() { | |
| 1253 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1254 blink::WebAXObject obj = accessibility_object_.headerContainerObject(); | |
| 1255 if (obj.isNull()) | |
| 1256 return v8::Local<v8::Object>(); | |
| 1257 | |
| 1258 return factory_->GetOrCreate(obj); | |
| 1259 } | |
| 1260 | |
| 1261 v8::Local<v8::Object> WebAXObjectProxy::RowHeaderAtIndex(unsigned index) { | |
| 1262 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1263 blink::WebVector<blink::WebAXObject> headers; | |
| 1264 accessibility_object_.rowHeaders(headers); | |
| 1265 size_t headerCount = headers.size(); | |
| 1266 if (index >= headerCount) | |
| 1267 return v8::Local<v8::Object>(); | |
| 1268 | |
| 1269 return factory_->GetOrCreate(headers[index]); | |
| 1270 } | |
| 1271 | |
| 1272 v8::Local<v8::Object> WebAXObjectProxy::ColumnHeaderAtIndex(unsigned index) { | |
| 1273 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1274 blink::WebVector<blink::WebAXObject> headers; | |
| 1275 accessibility_object_.columnHeaders(headers); | |
| 1276 size_t headerCount = headers.size(); | |
| 1277 if (index >= headerCount) | |
| 1278 return v8::Local<v8::Object>(); | |
| 1279 | |
| 1280 return factory_->GetOrCreate(headers[index]); | |
| 1281 } | |
| 1282 | |
| 1283 std::string WebAXObjectProxy::RowIndexRange() { | |
| 1284 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1285 unsigned row_index = accessibility_object_.cellRowIndex(); | |
| 1286 unsigned row_span = accessibility_object_.cellRowSpan(); | |
| 1287 return base::StringPrintf("{%d, %d}", row_index, row_span); | |
| 1288 } | |
| 1289 | |
| 1290 std::string WebAXObjectProxy::ColumnIndexRange() { | |
| 1291 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1292 unsigned column_index = accessibility_object_.cellColumnIndex(); | |
| 1293 unsigned column_span = accessibility_object_.cellColumnSpan(); | |
| 1294 return base::StringPrintf("{%d, %d}", column_index, column_span); | |
| 1295 } | |
| 1296 | |
| 1297 v8::Local<v8::Object> WebAXObjectProxy::CellForColumnAndRow( | |
| 1298 int column, int row) { | |
| 1299 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1300 blink::WebAXObject obj = | |
| 1301 accessibility_object_.cellForColumnAndRow(column, row); | |
| 1302 if (obj.isNull()) | |
| 1303 return v8::Local<v8::Object>(); | |
| 1304 | |
| 1305 return factory_->GetOrCreate(obj); | |
| 1306 } | |
| 1307 | |
| 1308 void WebAXObjectProxy::SetSelectedTextRange(int selection_start, | |
| 1309 int length) { | |
| 1310 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1311 accessibility_object_.setSelectedTextRange(selection_start, | |
| 1312 selection_start + length); | |
| 1313 } | |
| 1314 | |
| 1315 void WebAXObjectProxy::SetSelection( | |
| 1316 v8::Local<v8::Value> anchor_object, int anchor_offset, | |
| 1317 v8::Local<v8::Value> focus_object, int focus_offset) { | |
| 1318 if (anchor_object.IsEmpty() || focus_object.IsEmpty() || | |
| 1319 !anchor_object->IsObject() || !focus_object->IsObject() || | |
| 1320 anchor_offset < 0 || focus_offset < 0) { | |
| 1321 return; | |
| 1322 } | |
| 1323 | |
| 1324 WebAXObjectProxy* web_ax_anchor = nullptr; | |
| 1325 if (!gin::ConvertFromV8( | |
| 1326 blink::mainThreadIsolate(), anchor_object, &web_ax_anchor)) { | |
| 1327 return; | |
| 1328 } | |
| 1329 DCHECK(web_ax_anchor); | |
| 1330 | |
| 1331 WebAXObjectProxy* web_ax_focus = nullptr; | |
| 1332 if (!gin::ConvertFromV8( | |
| 1333 blink::mainThreadIsolate(), focus_object, &web_ax_focus)) { | |
| 1334 return; | |
| 1335 } | |
| 1336 DCHECK(web_ax_focus); | |
| 1337 | |
| 1338 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1339 accessibility_object_.setSelection( | |
| 1340 web_ax_anchor->accessibility_object_, anchor_offset, | |
| 1341 web_ax_focus->accessibility_object_, focus_offset); | |
| 1342 } | |
| 1343 | |
| 1344 bool WebAXObjectProxy::IsAttributeSettable(const std::string& attribute) { | |
| 1345 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1346 bool settable = false; | |
| 1347 if (attribute == "AXValue") | |
| 1348 settable = accessibility_object_.canSetValueAttribute(); | |
| 1349 return settable; | |
| 1350 } | |
| 1351 | |
| 1352 bool WebAXObjectProxy::IsPressActionSupported() { | |
| 1353 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1354 return accessibility_object_.canPress(); | |
| 1355 } | |
| 1356 | |
| 1357 bool WebAXObjectProxy::IsIncrementActionSupported() { | |
| 1358 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1359 return accessibility_object_.canIncrement(); | |
| 1360 } | |
| 1361 | |
| 1362 bool WebAXObjectProxy::IsDecrementActionSupported() { | |
| 1363 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1364 return accessibility_object_.canDecrement(); | |
| 1365 } | |
| 1366 | |
| 1367 v8::Local<v8::Object> WebAXObjectProxy::ParentElement() { | |
| 1368 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1369 blink::WebAXObject parent_object = accessibility_object_.parentObject(); | |
| 1370 while (parent_object.accessibilityIsIgnored()) | |
| 1371 parent_object = parent_object.parentObject(); | |
| 1372 return factory_->GetOrCreate(parent_object); | |
| 1373 } | |
| 1374 | |
| 1375 void WebAXObjectProxy::Increment() { | |
| 1376 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1377 accessibility_object_.increment(); | |
| 1378 } | |
| 1379 | |
| 1380 void WebAXObjectProxy::Decrement() { | |
| 1381 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1382 accessibility_object_.decrement(); | |
| 1383 } | |
| 1384 | |
| 1385 void WebAXObjectProxy::ShowMenu() { | |
| 1386 accessibility_object_.showContextMenu(); | |
| 1387 } | |
| 1388 | |
| 1389 void WebAXObjectProxy::Press() { | |
| 1390 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1391 accessibility_object_.press(); | |
| 1392 } | |
| 1393 | |
| 1394 bool WebAXObjectProxy::SetValue(const std::string& value) { | |
| 1395 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1396 if (!accessibility_object_.canSetValueAttribute()) | |
| 1397 return false; | |
| 1398 | |
| 1399 accessibility_object_.setValue(blink::WebString::fromUTF8(value)); | |
| 1400 return true; | |
| 1401 } | |
| 1402 | |
| 1403 bool WebAXObjectProxy::IsEqual(v8::Local<v8::Object> proxy) { | |
| 1404 WebAXObjectProxy* unwrapped_proxy = NULL; | |
| 1405 if (!gin::ConvertFromV8(blink::mainThreadIsolate(), proxy, &unwrapped_proxy)) | |
| 1406 return false; | |
| 1407 return unwrapped_proxy->IsEqualToObject(accessibility_object_); | |
| 1408 } | |
| 1409 | |
| 1410 void WebAXObjectProxy::SetNotificationListener( | |
| 1411 v8::Local<v8::Function> callback) { | |
| 1412 v8::Isolate* isolate = blink::mainThreadIsolate(); | |
| 1413 notification_callback_.Reset(isolate, callback); | |
| 1414 } | |
| 1415 | |
| 1416 void WebAXObjectProxy::UnsetNotificationListener() { | |
| 1417 notification_callback_.Reset(); | |
| 1418 } | |
| 1419 | |
| 1420 void WebAXObjectProxy::TakeFocus() { | |
| 1421 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1422 accessibility_object_.setFocused(true); | |
| 1423 } | |
| 1424 | |
| 1425 void WebAXObjectProxy::ScrollToMakeVisible() { | |
| 1426 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1427 accessibility_object_.scrollToMakeVisible(); | |
| 1428 } | |
| 1429 | |
| 1430 void WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus(int x, int y, | |
| 1431 int width, int height) { | |
| 1432 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1433 accessibility_object_.scrollToMakeVisibleWithSubFocus( | |
| 1434 blink::WebRect(x, y, width, height)); | |
| 1435 } | |
| 1436 | |
| 1437 void WebAXObjectProxy::ScrollToGlobalPoint(int x, int y) { | |
| 1438 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1439 accessibility_object_.scrollToGlobalPoint(blink::WebPoint(x, y)); | |
| 1440 } | |
| 1441 | |
| 1442 int WebAXObjectProxy::ScrollX() { | |
| 1443 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1444 return accessibility_object_.getScrollOffset().x; | |
| 1445 } | |
| 1446 | |
| 1447 int WebAXObjectProxy::ScrollY() { | |
| 1448 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1449 return accessibility_object_.getScrollOffset().y; | |
| 1450 } | |
| 1451 | |
| 1452 float WebAXObjectProxy::BoundsX() { | |
| 1453 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1454 return BoundsForObject(accessibility_object_).x; | |
| 1455 } | |
| 1456 | |
| 1457 float WebAXObjectProxy::BoundsY() { | |
| 1458 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1459 return BoundsForObject(accessibility_object_).y; | |
| 1460 } | |
| 1461 | |
| 1462 float WebAXObjectProxy::BoundsWidth() { | |
| 1463 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1464 return BoundsForObject(accessibility_object_).width; | |
| 1465 } | |
| 1466 | |
| 1467 float WebAXObjectProxy::BoundsHeight() { | |
| 1468 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1469 return BoundsForObject(accessibility_object_).height; | |
| 1470 } | |
| 1471 | |
| 1472 int WebAXObjectProxy::WordStart(int character_index) { | |
| 1473 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1474 if (accessibility_object_.role() != blink::WebAXRoleStaticText) | |
| 1475 return -1; | |
| 1476 | |
| 1477 int word_start = 0, word_end = 0; | |
| 1478 GetBoundariesForOneWord(accessibility_object_, character_index, | |
| 1479 word_start, word_end); | |
| 1480 return word_start; | |
| 1481 } | |
| 1482 | |
| 1483 int WebAXObjectProxy::WordEnd(int character_index) { | |
| 1484 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1485 if (accessibility_object_.role() != blink::WebAXRoleStaticText) | |
| 1486 return -1; | |
| 1487 | |
| 1488 int word_start = 0, word_end = 0; | |
| 1489 GetBoundariesForOneWord(accessibility_object_, character_index, | |
| 1490 word_start, word_end); | |
| 1491 return word_end; | |
| 1492 } | |
| 1493 | |
| 1494 v8::Local<v8::Object> WebAXObjectProxy::NextOnLine() { | |
| 1495 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1496 blink::WebAXObject obj = accessibility_object_.nextOnLine(); | |
| 1497 if (obj.isNull()) | |
| 1498 return v8::Local<v8::Object>(); | |
| 1499 | |
| 1500 return factory_->GetOrCreate(obj); | |
| 1501 } | |
| 1502 | |
| 1503 v8::Local<v8::Object> WebAXObjectProxy::PreviousOnLine() { | |
| 1504 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1505 blink::WebAXObject obj = accessibility_object_.previousOnLine(); | |
| 1506 if (obj.isNull()) | |
| 1507 return v8::Local<v8::Object>(); | |
| 1508 | |
| 1509 return factory_->GetOrCreate(obj); | |
| 1510 } | |
| 1511 | |
| 1512 std::string WebAXObjectProxy::MisspellingAtIndex(int index) { | |
| 1513 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1514 if (index < 0 || index >= MisspellingsCount()) | |
| 1515 return std::string(); | |
| 1516 return GetMisspellings(accessibility_object_)[index]; | |
| 1517 } | |
| 1518 | |
| 1519 std::string WebAXObjectProxy::Name() { | |
| 1520 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1521 return accessibility_object_.name().utf8(); | |
| 1522 } | |
| 1523 | |
| 1524 std::string WebAXObjectProxy::NameFrom() { | |
| 1525 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1526 blink::WebAXNameFrom nameFrom = blink::WebAXNameFromUninitialized; | |
| 1527 blink::WebVector<blink::WebAXObject> nameObjects; | |
| 1528 accessibility_object_.name(nameFrom, nameObjects); | |
| 1529 switch(nameFrom) { | |
| 1530 case blink::WebAXNameFromUninitialized: | |
| 1531 return ""; | |
| 1532 case blink::WebAXNameFromAttribute: | |
| 1533 return "attribute"; | |
| 1534 case blink::WebAXNameFromCaption: | |
| 1535 return "caption"; | |
| 1536 case blink::WebAXNameFromContents: | |
| 1537 return "contents"; | |
| 1538 case blink::WebAXNameFromPlaceholder: | |
| 1539 return "placeholder"; | |
| 1540 case blink::WebAXNameFromRelatedElement: | |
| 1541 return "relatedElement"; | |
| 1542 case blink::WebAXNameFromValue: | |
| 1543 return "value"; | |
| 1544 case blink::WebAXNameFromTitle: | |
| 1545 return "title"; | |
| 1546 } | |
| 1547 | |
| 1548 NOTREACHED(); | |
| 1549 return std::string(); | |
| 1550 } | |
| 1551 | |
| 1552 int WebAXObjectProxy::NameElementCount() { | |
| 1553 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1554 blink::WebAXNameFrom nameFrom; | |
| 1555 blink::WebVector<blink::WebAXObject> nameObjects; | |
| 1556 accessibility_object_.name(nameFrom, nameObjects); | |
| 1557 return static_cast<int>(nameObjects.size()); | |
| 1558 } | |
| 1559 | |
| 1560 v8::Local<v8::Object> WebAXObjectProxy::NameElementAtIndex(unsigned index) { | |
| 1561 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1562 blink::WebAXNameFrom nameFrom; | |
| 1563 blink::WebVector<blink::WebAXObject> nameObjects; | |
| 1564 accessibility_object_.name(nameFrom, nameObjects); | |
| 1565 if (index >= nameObjects.size()) | |
| 1566 return v8::Local<v8::Object>(); | |
| 1567 return factory_->GetOrCreate(nameObjects[index]); | |
| 1568 } | |
| 1569 | |
| 1570 std::string WebAXObjectProxy::Description() { | |
| 1571 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1572 blink::WebAXNameFrom nameFrom; | |
| 1573 blink::WebVector<blink::WebAXObject> nameObjects; | |
| 1574 accessibility_object_.name(nameFrom, nameObjects); | |
| 1575 blink::WebAXDescriptionFrom descriptionFrom; | |
| 1576 blink::WebVector<blink::WebAXObject> descriptionObjects; | |
| 1577 return accessibility_object_.description( | |
| 1578 nameFrom, descriptionFrom, descriptionObjects).utf8(); | |
| 1579 } | |
| 1580 | |
| 1581 std::string WebAXObjectProxy::DescriptionFrom() { | |
| 1582 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1583 blink::WebAXNameFrom nameFrom; | |
| 1584 blink::WebVector<blink::WebAXObject> nameObjects; | |
| 1585 accessibility_object_.name(nameFrom, nameObjects); | |
| 1586 blink::WebAXDescriptionFrom descriptionFrom = | |
| 1587 blink::WebAXDescriptionFromUninitialized; | |
| 1588 blink::WebVector<blink::WebAXObject> descriptionObjects; | |
| 1589 accessibility_object_.description( | |
| 1590 nameFrom, descriptionFrom, descriptionObjects); | |
| 1591 switch(descriptionFrom) { | |
| 1592 case blink::WebAXDescriptionFromUninitialized: | |
| 1593 return ""; | |
| 1594 case blink::WebAXDescriptionFromAttribute: | |
| 1595 return "attribute"; | |
| 1596 case blink::WebAXDescriptionFromContents: | |
| 1597 return "contents"; | |
| 1598 case blink::WebAXDescriptionFromRelatedElement: | |
| 1599 return "relatedElement"; | |
| 1600 } | |
| 1601 | |
| 1602 NOTREACHED(); | |
| 1603 return std::string(); | |
| 1604 } | |
| 1605 | |
| 1606 std::string WebAXObjectProxy::Placeholder() { | |
| 1607 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1608 blink::WebAXNameFrom nameFrom; | |
| 1609 blink::WebVector<blink::WebAXObject> nameObjects; | |
| 1610 accessibility_object_.name(nameFrom, nameObjects); | |
| 1611 return accessibility_object_.placeholder(nameFrom).utf8(); | |
| 1612 } | |
| 1613 | |
| 1614 int WebAXObjectProxy::MisspellingsCount() { | |
| 1615 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1616 return GetMisspellings(accessibility_object_).size(); | |
| 1617 } | |
| 1618 | |
| 1619 int WebAXObjectProxy::DescriptionElementCount() { | |
| 1620 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1621 blink::WebAXNameFrom nameFrom; | |
| 1622 blink::WebVector<blink::WebAXObject> nameObjects; | |
| 1623 accessibility_object_.name(nameFrom, nameObjects); | |
| 1624 blink::WebAXDescriptionFrom descriptionFrom; | |
| 1625 blink::WebVector<blink::WebAXObject> descriptionObjects; | |
| 1626 accessibility_object_.description( | |
| 1627 nameFrom, descriptionFrom, descriptionObjects); | |
| 1628 return static_cast<int>(descriptionObjects.size()); | |
| 1629 } | |
| 1630 | |
| 1631 v8::Local<v8::Object> WebAXObjectProxy::DescriptionElementAtIndex( | |
| 1632 unsigned index) { | |
| 1633 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1634 blink::WebAXNameFrom nameFrom; | |
| 1635 blink::WebVector<blink::WebAXObject> nameObjects; | |
| 1636 accessibility_object_.name(nameFrom, nameObjects); | |
| 1637 blink::WebAXDescriptionFrom descriptionFrom; | |
| 1638 blink::WebVector<blink::WebAXObject> descriptionObjects; | |
| 1639 accessibility_object_.description( | |
| 1640 nameFrom, descriptionFrom, descriptionObjects); | |
| 1641 if (index >= descriptionObjects.size()) | |
| 1642 return v8::Local<v8::Object>(); | |
| 1643 return factory_->GetOrCreate(descriptionObjects[index]); | |
| 1644 } | |
| 1645 | |
| 1646 v8::Local<v8::Object> WebAXObjectProxy::OffsetContainer() { | |
| 1647 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1648 blink::WebAXObject container; | |
| 1649 blink::WebFloatRect bounds; | |
| 1650 SkMatrix44 matrix; | |
| 1651 accessibility_object_.getRelativeBounds(container, bounds, matrix); | |
| 1652 return factory_->GetOrCreate(container); | |
| 1653 } | |
| 1654 | |
| 1655 float WebAXObjectProxy::BoundsInContainerX() { | |
| 1656 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1657 blink::WebAXObject container; | |
| 1658 blink::WebFloatRect bounds; | |
| 1659 SkMatrix44 matrix; | |
| 1660 accessibility_object_.getRelativeBounds(container, bounds, matrix); | |
| 1661 return bounds.x; | |
| 1662 } | |
| 1663 | |
| 1664 float WebAXObjectProxy::BoundsInContainerY() { | |
| 1665 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1666 blink::WebAXObject container; | |
| 1667 blink::WebFloatRect bounds; | |
| 1668 SkMatrix44 matrix; | |
| 1669 accessibility_object_.getRelativeBounds(container, bounds, matrix); | |
| 1670 return bounds.y; | |
| 1671 } | |
| 1672 | |
| 1673 float WebAXObjectProxy::BoundsInContainerWidth() { | |
| 1674 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1675 blink::WebAXObject container; | |
| 1676 blink::WebFloatRect bounds; | |
| 1677 SkMatrix44 matrix; | |
| 1678 accessibility_object_.getRelativeBounds(container, bounds, matrix); | |
| 1679 return bounds.width; | |
| 1680 } | |
| 1681 | |
| 1682 float WebAXObjectProxy::BoundsInContainerHeight() { | |
| 1683 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1684 blink::WebAXObject container; | |
| 1685 blink::WebFloatRect bounds; | |
| 1686 SkMatrix44 matrix; | |
| 1687 accessibility_object_.getRelativeBounds(container, bounds, matrix); | |
| 1688 return bounds.height; | |
| 1689 } | |
| 1690 | |
| 1691 bool WebAXObjectProxy::HasNonIdentityTransform() { | |
| 1692 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1693 accessibility_object_.updateLayoutAndCheckValidity(); | |
| 1694 blink::WebAXObject container; | |
| 1695 blink::WebFloatRect bounds; | |
| 1696 SkMatrix44 matrix; | |
| 1697 accessibility_object_.getRelativeBounds(container, bounds, matrix); | |
| 1698 return !matrix.isIdentity(); | |
| 1699 } | |
| 1700 | |
| 1701 RootWebAXObjectProxy::RootWebAXObjectProxy( | |
| 1702 const blink::WebAXObject &object, Factory *factory) | |
| 1703 : WebAXObjectProxy(object, factory) { | |
| 1704 } | |
| 1705 | |
| 1706 v8::Local<v8::Object> RootWebAXObjectProxy::GetChildAtIndex(unsigned index) { | |
| 1707 if (index) | |
| 1708 return v8::Local<v8::Object>(); | |
| 1709 | |
| 1710 return factory()->GetOrCreate(accessibility_object()); | |
| 1711 } | |
| 1712 | |
| 1713 bool RootWebAXObjectProxy::IsRoot() const { | |
| 1714 return true; | |
| 1715 } | |
| 1716 | |
| 1717 WebAXObjectProxyList::WebAXObjectProxyList() | |
| 1718 : elements_(blink::mainThreadIsolate()) { | |
| 1719 } | |
| 1720 | |
| 1721 WebAXObjectProxyList::~WebAXObjectProxyList() { | |
| 1722 Clear(); | |
| 1723 } | |
| 1724 | |
| 1725 void WebAXObjectProxyList::Clear() { | |
| 1726 v8::Isolate* isolate = blink::mainThreadIsolate(); | |
| 1727 v8::HandleScope handle_scope(isolate); | |
| 1728 size_t elementCount = elements_.Size(); | |
| 1729 for (size_t i = 0; i < elementCount; i++) { | |
| 1730 WebAXObjectProxy* unwrapped_object = NULL; | |
| 1731 bool result = gin::ConvertFromV8(isolate, elements_.Get(i), | |
| 1732 &unwrapped_object); | |
| 1733 DCHECK(result); | |
| 1734 DCHECK(unwrapped_object); | |
| 1735 unwrapped_object->Reset(); | |
| 1736 } | |
| 1737 elements_.Clear(); | |
| 1738 } | |
| 1739 | |
| 1740 v8::Local<v8::Object> WebAXObjectProxyList::GetOrCreate( | |
| 1741 const blink::WebAXObject& object) { | |
| 1742 if (object.isNull()) | |
| 1743 return v8::Local<v8::Object>(); | |
| 1744 | |
| 1745 v8::Isolate* isolate = blink::mainThreadIsolate(); | |
| 1746 | |
| 1747 size_t elementCount = elements_.Size(); | |
| 1748 for (size_t i = 0; i < elementCount; i++) { | |
| 1749 WebAXObjectProxy* unwrapped_object = NULL; | |
| 1750 bool result = gin::ConvertFromV8(isolate, elements_.Get(i), | |
| 1751 &unwrapped_object); | |
| 1752 DCHECK(result); | |
| 1753 DCHECK(unwrapped_object); | |
| 1754 if (unwrapped_object->IsEqualToObject(object)) | |
| 1755 return elements_.Get(i); | |
| 1756 } | |
| 1757 | |
| 1758 v8::Local<v8::Value> value_handle = gin::CreateHandle( | |
| 1759 isolate, new WebAXObjectProxy(object, this)).ToV8(); | |
| 1760 if (value_handle.IsEmpty()) | |
| 1761 return v8::Local<v8::Object>(); | |
| 1762 v8::Local<v8::Object> handle = value_handle->ToObject(isolate); | |
| 1763 elements_.Append(handle); | |
| 1764 return handle; | |
| 1765 } | |
| 1766 | |
| 1767 } // namespace test_runner | |
| OLD | NEW |