OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/glue/webaccessibility.h" | 5 #include "webkit/glue/webaccessibility.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
11 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityCache
.h" | 12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityCache
.h" |
13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityObjec
t.h" | 13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityObjec
t.h" |
14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityRole.
h" | 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityRole.
h" |
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAttribute.h" | 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAttribute.h" |
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocumentType.h" | 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocumentType.h" |
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" | 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" |
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement
.h" | 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFormControlElement
.h" |
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h" | 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h" |
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNamedNodeMap.h" | 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNamedNodeMap.h" |
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" | 23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" |
24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h" | 24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h" |
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" | 25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" |
26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" | 26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" |
27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h" | 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h" |
28 | 28 |
| 29 using base::DoubleToString; |
| 30 using base::IntToString; |
29 using WebKit::WebAccessibilityCache; | 31 using WebKit::WebAccessibilityCache; |
30 using WebKit::WebAccessibilityRole; | 32 using WebKit::WebAccessibilityRole; |
31 using WebKit::WebAccessibilityObject; | 33 using WebKit::WebAccessibilityObject; |
32 | 34 |
| 35 namespace { |
| 36 |
| 37 std::string IntVectorToString(const std::vector<int>& items) { |
| 38 std::string str; |
| 39 for (size_t i = 0; i < items.size(); ++i) { |
| 40 if (i > 0) |
| 41 str += ","; |
| 42 str += IntToString(items[i]); |
| 43 } |
| 44 return str; |
| 45 } |
| 46 |
| 47 } // Anonymous namespace |
| 48 |
33 namespace webkit_glue { | 49 namespace webkit_glue { |
34 | 50 |
35 // Provides a conversion between the WebKit::WebAccessibilityRole and a role | 51 // Provides a conversion between the WebKit::WebAccessibilityRole and a role |
36 // supported on the Browser side. Listed alphabetically by the | 52 // supported on the Browser side. Listed alphabetically by the |
37 // WebAccessibilityRole (except for default role). | 53 // WebAccessibilityRole (except for default role). |
38 WebAccessibility::Role ConvertRole(WebKit::WebAccessibilityRole role) { | 54 WebAccessibility::Role ConvertRole(WebKit::WebAccessibilityRole role) { |
39 switch (role) { | 55 switch (role) { |
40 case WebKit::WebAccessibilityRoleAnnotation: | 56 case WebKit::WebAccessibilityRoleAnnotation: |
41 return WebAccessibility::ROLE_ANNOTATION; | 57 return WebAccessibility::ROLE_ANNOTATION; |
42 case WebKit::WebAccessibilityRoleApplication: | 58 case WebKit::WebAccessibilityRoleApplication: |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 | 254 |
239 if (o.isCollapsed()) | 255 if (o.isCollapsed()) |
240 state |= (1 << WebAccessibility::STATE_COLLAPSED); | 256 state |= (1 << WebAccessibility::STATE_COLLAPSED); |
241 | 257 |
242 if (o.canSetFocusAttribute()) | 258 if (o.canSetFocusAttribute()) |
243 state |= (1 << WebAccessibility::STATE_FOCUSABLE); | 259 state |= (1 << WebAccessibility::STATE_FOCUSABLE); |
244 | 260 |
245 if (o.isFocused()) | 261 if (o.isFocused()) |
246 state |= (1 << WebAccessibility::STATE_FOCUSED); | 262 state |= (1 << WebAccessibility::STATE_FOCUSED); |
247 | 263 |
248 if (o.roleValue() == WebKit::WebAccessibilityRolePopUpButton) { | 264 if (o.roleValue() == WebKit::WebAccessibilityRolePopUpButton || |
| 265 o.ariaHasPopup()) { |
249 state |= (1 << WebAccessibility::STATE_HASPOPUP); | 266 state |= (1 << WebAccessibility::STATE_HASPOPUP); |
250 | |
251 if (!o.isCollapsed()) | 267 if (!o.isCollapsed()) |
252 state |= (1 << WebAccessibility::STATE_EXPANDED); | 268 state |= (1 << WebAccessibility::STATE_EXPANDED); |
253 } | 269 } |
254 | 270 |
255 if (o.isHovered()) | 271 if (o.isHovered()) |
256 state |= (1 << WebAccessibility::STATE_HOTTRACKED); | 272 state |= (1 << WebAccessibility::STATE_HOTTRACKED); |
257 | 273 |
258 if (o.isIndeterminate()) | 274 if (o.isIndeterminate()) |
259 state |= (1 << WebAccessibility::STATE_INDETERMINATE); | 275 state |= (1 << WebAccessibility::STATE_INDETERMINATE); |
260 | 276 |
261 if (!o.isVisible()) | 277 if (!o.isVisible()) |
262 state |= (1 << WebAccessibility::STATE_INVISIBLE); | 278 state |= (1 << WebAccessibility::STATE_INVISIBLE); |
263 | 279 |
264 if (o.isLinked()) | 280 if (o.isLinked()) |
265 state |= (1 << WebAccessibility::STATE_LINKED); | 281 state |= (1 << WebAccessibility::STATE_LINKED); |
266 | 282 |
267 if (o.isMultiSelectable()) | 283 if (o.isMultiSelectable()) |
268 state |= (1 << WebAccessibility::STATE_MULTISELECTABLE); | 284 state |= (1 << WebAccessibility::STATE_MULTISELECTABLE); |
269 | 285 |
270 if (o.isOffScreen()) | 286 if (o.isOffScreen()) |
271 state |= (1 << WebAccessibility::STATE_OFFSCREEN); | 287 state |= (1 << WebAccessibility::STATE_OFFSCREEN); |
272 | 288 |
273 if (o.isPressed()) | 289 if (o.isPressed()) |
274 state |= (1 << WebAccessibility::STATE_PRESSED); | 290 state |= (1 << WebAccessibility::STATE_PRESSED); |
275 | 291 |
276 if (o.isPasswordField()) | 292 if (o.isPasswordField()) |
277 state |= (1 << WebAccessibility::STATE_PROTECTED); | 293 state |= (1 << WebAccessibility::STATE_PROTECTED); |
278 | 294 |
279 if (o.isReadOnly()) | 295 if (o.isAriaReadOnly()) |
280 state |= (1 << WebAccessibility::STATE_READONLY); | 296 state |= (1 << WebAccessibility::STATE_READONLY); |
281 | 297 |
| 298 if (o.isRequired()) |
| 299 state |= (1 << WebAccessibility::STATE_REQUIRED); |
| 300 |
282 if (o.canSetSelectedAttribute()) | 301 if (o.canSetSelectedAttribute()) |
283 state |= (1 << WebAccessibility::STATE_SELECTABLE); | 302 state |= (1 << WebAccessibility::STATE_SELECTABLE); |
284 | 303 |
285 if (o.isSelected()) | 304 if (o.isSelected()) |
286 state |= (1 << WebAccessibility::STATE_SELECTED); | 305 state |= (1 << WebAccessibility::STATE_SELECTED); |
287 | 306 |
288 if (o.isVisited()) | 307 if (o.isVisited()) |
289 state |= (1 << WebAccessibility::STATE_TRAVERSED); | 308 state |= (1 << WebAccessibility::STATE_TRAVERSED); |
290 | 309 |
291 if (!o.isEnabled()) | 310 if (!o.isEnabled()) |
292 state |= (1 << WebAccessibility::STATE_UNAVAILABLE); | 311 state |= (1 << WebAccessibility::STATE_UNAVAILABLE); |
293 | 312 |
| 313 if (o.isVertical()) |
| 314 state |= (1 << WebAccessibility::STATE_VERTICAL); |
| 315 |
| 316 if (o.isVisited()) |
| 317 state |= (1 << WebAccessibility::STATE_VISITED); |
| 318 |
294 return state; | 319 return state; |
295 } | 320 } |
296 | 321 |
297 WebAccessibility::WebAccessibility() | 322 WebAccessibility::WebAccessibility() |
298 : id(-1), | 323 : id(-1), |
299 role(ROLE_NONE), | 324 role(ROLE_NONE), |
300 state(-1) { | 325 state(-1) { |
301 } | 326 } |
302 | 327 |
303 WebAccessibility::WebAccessibility(const WebKit::WebAccessibilityObject& src, | 328 WebAccessibility::WebAccessibility(const WebKit::WebAccessibilityObject& src, |
304 WebKit::WebAccessibilityCache* cache, | 329 WebKit::WebAccessibilityCache* cache, |
305 bool include_children) { | 330 bool include_children) { |
306 Init(src, cache, include_children); | 331 Init(src, cache, include_children); |
307 } | 332 } |
308 | 333 |
309 WebAccessibility::~WebAccessibility() { | 334 WebAccessibility::~WebAccessibility() { |
310 } | 335 } |
311 | 336 |
| 337 #ifndef NDEBUG |
| 338 std::string WebAccessibility::DebugString(bool recursive) { |
| 339 std::string result; |
| 340 static int indent = 0; |
| 341 |
| 342 for (int i = 0; i < indent; ++i) |
| 343 result += " "; |
| 344 |
| 345 result += "id=" + IntToString(id); |
| 346 |
| 347 switch (role) { |
| 348 case ROLE_ALERT: result += " ALERT"; break; |
| 349 case ROLE_ALERT_DIALOG: result += " ALERT_DIALOG"; break; |
| 350 case ROLE_ANNOTATION: result += " ANNOTATION"; break; |
| 351 case ROLE_APPLICATION: result += " APPLICATION"; break; |
| 352 case ROLE_ARTICLE: result += " ARTICLE"; break; |
| 353 case ROLE_BROWSER: result += " BROWSER"; break; |
| 354 case ROLE_BUSY_INDICATOR: result += " BUSY_INDICATOR"; break; |
| 355 case ROLE_BUTTON: result += " BUTTON"; break; |
| 356 case ROLE_CELL: result += " CELL"; break; |
| 357 case ROLE_CHECKBOX: result += " CHECKBOX"; break; |
| 358 case ROLE_COLOR_WELL: result += " COLOR_WELL"; break; |
| 359 case ROLE_COLUMN: result += " COLUMN"; break; |
| 360 case ROLE_COLUMN_HEADER: result += " COLUMN_HEADER"; break; |
| 361 case ROLE_COMBO_BOX: result += " COMBO_BOX"; break; |
| 362 case ROLE_DEFINITION_LIST_DEFINITION: result += " DL_DEFINITION"; break; |
| 363 case ROLE_DEFINITION_LIST_TERM: result += " DL_TERM"; break; |
| 364 case ROLE_DIALOG: result += " DIALOG"; break; |
| 365 case ROLE_DIRECTORY: result += " DIRECTORY"; break; |
| 366 case ROLE_DISCLOSURE_TRIANGLE: result += " DISCLOSURE_TRIANGLE"; break; |
| 367 case ROLE_DOCUMENT: result += " DOCUMENT"; break; |
| 368 case ROLE_DRAWER: result += " DRAWER"; break; |
| 369 case ROLE_EDITABLE_TEXT: result += " EDITABLE_TEXT"; break; |
| 370 case ROLE_GRID: result += " GRID"; break; |
| 371 case ROLE_GROUP: result += " GROUP"; break; |
| 372 case ROLE_GROW_AREA: result += " GROW_AREA"; break; |
| 373 case ROLE_HEADING: result += " HEADING"; break; |
| 374 case ROLE_HELP_TAG: result += " HELP_TAG"; break; |
| 375 case ROLE_IGNORED: result += " IGNORED"; break; |
| 376 case ROLE_IMAGE: result += " IMAGE"; break; |
| 377 case ROLE_IMAGE_MAP: result += " IMAGE_MAP"; break; |
| 378 case ROLE_IMAGE_MAP_LINK: result += " IMAGE_MAP_LINK"; break; |
| 379 case ROLE_INCREMENTOR: result += " INCREMENTOR"; break; |
| 380 case ROLE_LANDMARK_APPLICATION: result += " L_APPLICATION"; break; |
| 381 case ROLE_LANDMARK_BANNER: result += " L_BANNER"; break; |
| 382 case ROLE_LANDMARK_COMPLEMENTARY: result += " L_COMPLEMENTARY"; break; |
| 383 case ROLE_LANDMARK_CONTENTINFO: result += " L_CONTENTINFO"; break; |
| 384 case ROLE_LANDMARK_MAIN: result += " L_MAIN"; break; |
| 385 case ROLE_LANDMARK_NAVIGATION: result += " L_NAVIGATION"; break; |
| 386 case ROLE_LANDMARK_SEARCH: result += " L_SEARCH"; break; |
| 387 case ROLE_LINK: result += " LINK"; break; |
| 388 case ROLE_LIST: result += " LIST"; break; |
| 389 case ROLE_LISTBOX: result += " LISTBOX"; break; |
| 390 case ROLE_LISTBOX_OPTION: result += " LISTBOX_OPTION"; break; |
| 391 case ROLE_LIST_ITEM: result += " LIST_ITEM"; break; |
| 392 case ROLE_LIST_MARKER: result += " LIST_MARKER"; break; |
| 393 case ROLE_LOG: result += " LOG"; break; |
| 394 case ROLE_MARQUEE: result += " MARQUEE"; break; |
| 395 case ROLE_MATH: result += " MATH"; break; |
| 396 case ROLE_MATTE: result += " MATTE"; break; |
| 397 case ROLE_MENU: result += " MENU"; break; |
| 398 case ROLE_MENU_BAR: result += " MENU_BAR"; break; |
| 399 case ROLE_MENU_BUTTON: result += " MENU_BUTTON"; break; |
| 400 case ROLE_MENU_ITEM: result += " MENU_ITEM"; break; |
| 401 case ROLE_MENU_LIST_OPTION: result += " MENU_LIST_OPTION"; break; |
| 402 case ROLE_MENU_LIST_POPUP: result += " MENU_LIST_POPUP"; break; |
| 403 case ROLE_NOTE: result += " NOTE"; break; |
| 404 case ROLE_OUTLINE: result += " OUTLINE"; break; |
| 405 case ROLE_POPUP_BUTTON: result += " POPUP_BUTTON"; break; |
| 406 case ROLE_PROGRESS_INDICATOR: result += " PROGRESS_INDICATOR"; break; |
| 407 case ROLE_RADIO_BUTTON: result += " RADIO_BUTTON"; break; |
| 408 case ROLE_RADIO_GROUP: result += " RADIO_GROUP"; break; |
| 409 case ROLE_REGION: result += " REGION"; break; |
| 410 case ROLE_ROW: result += " ROW"; break; |
| 411 case ROLE_ROW_HEADER: result += " ROW_HEADER"; break; |
| 412 case ROLE_RULER: result += " RULER"; break; |
| 413 case ROLE_RULER_MARKER: result += " RULER_MARKER"; break; |
| 414 case ROLE_SCROLLAREA: result += " SCROLLAREA"; break; |
| 415 case ROLE_SCROLLBAR: result += " SCROLLBAR"; break; |
| 416 case ROLE_SHEET: result += " SHEET"; break; |
| 417 case ROLE_SLIDER: result += " SLIDER"; break; |
| 418 case ROLE_SLIDER_THUMB: result += " SLIDER_THUMB"; break; |
| 419 case ROLE_SPLITTER: result += " SPLITTER"; break; |
| 420 case ROLE_SPLIT_GROUP: result += " SPLIT_GROUP"; break; |
| 421 case ROLE_STATIC_TEXT: result += " STATIC_TEXT"; break; |
| 422 case ROLE_STATUS: result += " STATUS"; break; |
| 423 case ROLE_SYSTEM_WIDE: result += " SYSTEM_WIDE"; break; |
| 424 case ROLE_TAB: result += " TAB"; break; |
| 425 case ROLE_TABLE: result += " TABLE"; break; |
| 426 case ROLE_TABLE_HEADER_CONTAINER: result += " TABLE_HDR_CONTAINER"; break; |
| 427 case ROLE_TAB_GROUP: result += " TAB_GROUP"; break; |
| 428 case ROLE_TAB_LIST: result += " TAB_LIST"; break; |
| 429 case ROLE_TAB_PANEL: result += " TAB_PANEL"; break; |
| 430 case ROLE_TEXTAREA: result += " TEXTAREA"; break; |
| 431 case ROLE_TEXT_FIELD: result += " TEXT_FIELD"; break; |
| 432 case ROLE_TIMER: result += " TIMER"; break; |
| 433 case ROLE_TOOLBAR: result += " TOOLBAR"; break; |
| 434 case ROLE_TOOLTIP: result += " TOOLTIP"; break; |
| 435 case ROLE_TREE: result += " TREE"; break; |
| 436 case ROLE_TREE_GRID: result += " TREE_GRID"; break; |
| 437 case ROLE_TREE_ITEM: result += " TREE_ITEM"; break; |
| 438 case ROLE_UNKNOWN: result += " UNKNOWN"; break; |
| 439 case ROLE_VALUE_INDICATOR: result += " VALUE_INDICATOR"; break; |
| 440 case ROLE_WEBCORE_LINK: result += " WEBCORE_LINK"; break; |
| 441 case ROLE_WEB_AREA: result += " WEB_AREA"; break; |
| 442 case ROLE_WINDOW: result += " WINDOW"; break; |
| 443 default: |
| 444 assert(false); |
| 445 } |
| 446 |
| 447 if (state & (1 << STATE_BUSY)) |
| 448 result += " BUSY"; |
| 449 if (state & (1 << STATE_CHECKED)) |
| 450 result += " CHECKED"; |
| 451 if (state & (1 << STATE_COLLAPSED)) |
| 452 result += " COLLAPSED"; |
| 453 if (state & (1 << STATE_EXPANDED)) |
| 454 result += " EXPANDED"; |
| 455 if (state & (1 << STATE_FOCUSABLE)) |
| 456 result += " FOCUSABLE"; |
| 457 if (state & (1 << STATE_FOCUSED)) |
| 458 result += " FOCUSED"; |
| 459 if (state & (1 << STATE_HASPOPUP)) |
| 460 result += " HASPOPUP"; |
| 461 if (state & (1 << STATE_HOTTRACKED)) |
| 462 result += " HOTTRACKED"; |
| 463 if (state & (1 << STATE_INDETERMINATE)) |
| 464 result += " INDETERMINATE"; |
| 465 if (state & (1 << STATE_INVISIBLE)) |
| 466 result += " INVISIBLE"; |
| 467 if (state & (1 << STATE_LINKED)) |
| 468 result += " LINKED"; |
| 469 if (state & (1 << STATE_MULTISELECTABLE)) |
| 470 result += " MULTISELECTABLE"; |
| 471 if (state & (1 << STATE_OFFSCREEN)) |
| 472 result += " OFFSCREEN"; |
| 473 if (state & (1 << STATE_PRESSED)) |
| 474 result += " PRESSED"; |
| 475 if (state & (1 << STATE_PROTECTED)) |
| 476 result += " PROTECTED"; |
| 477 if (state & (1 << STATE_READONLY)) |
| 478 result += " READONLY"; |
| 479 if (state & (1 << STATE_REQUIRED)) |
| 480 result += " REQUIRED"; |
| 481 if (state & (1 << STATE_SELECTABLE)) |
| 482 result += " SELECTABLE"; |
| 483 if (state & (1 << STATE_SELECTED)) |
| 484 result += " SELECTED"; |
| 485 if (state & (1 << STATE_TRAVERSED)) |
| 486 result += " TRAVERSED"; |
| 487 if (state & (1 << STATE_UNAVAILABLE)) |
| 488 result += " UNAVAILABLE"; |
| 489 if (state & (1 << STATE_VERTICAL)) |
| 490 result += " VERTICAL"; |
| 491 if (state & (1 << STATE_VISITED)) |
| 492 result += " VISITED"; |
| 493 |
| 494 std::string tmp = UTF16ToUTF8(name); |
| 495 RemoveChars(tmp, "\n", &tmp); |
| 496 if (!tmp.empty()) |
| 497 result += " name=" + tmp; |
| 498 |
| 499 tmp = UTF16ToUTF8(value); |
| 500 RemoveChars(tmp, "\n", &tmp); |
| 501 if (!tmp.empty()) |
| 502 result += " value=" + tmp; |
| 503 |
| 504 result += " (" + IntToString(location.x()) + ", " + |
| 505 IntToString(location.y()) + ")-(" + |
| 506 IntToString(location.width()) + ", " + |
| 507 IntToString(location.height()) + ")"; |
| 508 |
| 509 for (std::map<IntAttribute, int32>::const_iterator iter = |
| 510 int_attributes.begin(); |
| 511 iter != int_attributes.end(); |
| 512 ++iter) { |
| 513 std::string value = IntToString(iter->second); |
| 514 switch (iter->first) { |
| 515 case ATTR_DOC_SCROLLX: |
| 516 result += " scrollx=" + value; |
| 517 break; |
| 518 case ATTR_DOC_SCROLLY: |
| 519 result += " scrolly=" + value; |
| 520 break; |
| 521 case ATTR_HIERARCHICAL_LEVEL: |
| 522 result += " level=" + value; |
| 523 break; |
| 524 case ATTR_TEXT_SEL_START: |
| 525 result += " sel_start=" + value; |
| 526 break; |
| 527 case ATTR_TEXT_SEL_END: |
| 528 result += " sel_end=" + value; |
| 529 break; |
| 530 case ATTR_TABLE_ROW_COUNT: |
| 531 result += " rows=" + value; |
| 532 break; |
| 533 case ATTR_TABLE_COLUMN_COUNT: |
| 534 result += " cols=" + value; |
| 535 break; |
| 536 case ATTR_TABLE_CELL_COLUMN_INDEX: |
| 537 result += " col=" + value; |
| 538 break; |
| 539 case ATTR_TABLE_CELL_ROW_INDEX: |
| 540 result += " row=" + value; |
| 541 break; |
| 542 case ATTR_TABLE_CELL_COLUMN_SPAN: |
| 543 result += " colspan=" + value; |
| 544 break; |
| 545 case ATTR_TABLE_CELL_ROW_SPAN: |
| 546 result += " rowspan=" + value; |
| 547 break; |
| 548 } |
| 549 } |
| 550 |
| 551 for (std::map<StringAttribute, string16>::const_iterator iter = |
| 552 string_attributes.begin(); |
| 553 iter != string_attributes.end(); |
| 554 ++iter) { |
| 555 std::string value = UTF16ToUTF8(iter->second); |
| 556 switch (iter->first) { |
| 557 case ATTR_DOC_URL: |
| 558 result += " doc_url=" + value; |
| 559 break; |
| 560 case ATTR_DOC_TITLE: |
| 561 result += " doc_title=" + value; |
| 562 break; |
| 563 case ATTR_DOC_MIMETYPE: |
| 564 result += " doc_mimetype=" + value; |
| 565 break; |
| 566 case ATTR_DOC_DOCTYPE: |
| 567 result += " doc_doctype=" + value; |
| 568 break; |
| 569 case ATTR_ACCESS_KEY: |
| 570 result += " access_key=" + value; |
| 571 break; |
| 572 case ATTR_ACTION: |
| 573 result += " action=" + value; |
| 574 break; |
| 575 case ATTR_DESCRIPTION: |
| 576 result += " description=" + value; |
| 577 break; |
| 578 case ATTR_DISPLAY: |
| 579 result += " display=" + value; |
| 580 break; |
| 581 case ATTR_HELP: |
| 582 result += " help=" + value; |
| 583 break; |
| 584 case ATTR_HTML_TAG: |
| 585 result += " html_tag=" + value; |
| 586 break; |
| 587 case ATTR_LIVE_RELEVANT: |
| 588 result += " relevant=" + value; |
| 589 break; |
| 590 case ATTR_LIVE_STATUS: |
| 591 result += " live=" + value; |
| 592 break; |
| 593 case ATTR_CONTAINER_LIVE_RELEVANT: |
| 594 result += " container_relevant=" + value; |
| 595 break; |
| 596 case ATTR_CONTAINER_LIVE_STATUS: |
| 597 result += " container_live=" + value; |
| 598 break; |
| 599 case ATTR_ROLE: |
| 600 result += " role=" + value; |
| 601 break; |
| 602 case ATTR_SHORTCUT: |
| 603 result += " shortcut=" + value; |
| 604 break; |
| 605 case ATTR_URL: |
| 606 result += " url=" + value; |
| 607 break; |
| 608 } |
| 609 } |
| 610 |
| 611 for (std::map<FloatAttribute, float>::const_iterator iter = |
| 612 float_attributes.begin(); |
| 613 iter != float_attributes.end(); |
| 614 ++iter) { |
| 615 std::string value = DoubleToString(iter->second); |
| 616 switch (iter->first) { |
| 617 case ATTR_DOC_LOADING_PROGRESS: |
| 618 result += " doc_progress=" + value; |
| 619 break; |
| 620 case ATTR_VALUE_FOR_RANGE: |
| 621 result += " value_for_range=" + value; |
| 622 break; |
| 623 case ATTR_MAX_VALUE_FOR_RANGE: |
| 624 result += " max_value=" + value; |
| 625 break; |
| 626 case ATTR_MIN_VALUE_FOR_RANGE: |
| 627 result += " min_value=" + value; |
| 628 break; |
| 629 } |
| 630 } |
| 631 |
| 632 for (std::map<BoolAttribute, bool>::const_iterator iter = |
| 633 bool_attributes.begin(); |
| 634 iter != bool_attributes.end(); |
| 635 ++iter) { |
| 636 std::string value = iter->second ? "true" : "false"; |
| 637 switch (iter->first) { |
| 638 case ATTR_DOC_LOADED: |
| 639 result += " doc_loaded=" + value; |
| 640 break; |
| 641 case ATTR_BUTTON_MIXED: |
| 642 result += " mixed=" + value; |
| 643 break; |
| 644 case ATTR_LIVE_ATOMIC: |
| 645 result += " atomic=" + value; |
| 646 break; |
| 647 case ATTR_LIVE_BUSY: |
| 648 result += " busy=" + value; |
| 649 break; |
| 650 case ATTR_CONTAINER_LIVE_ATOMIC: |
| 651 result += " container_atomic=" + value; |
| 652 break; |
| 653 case ATTR_CONTAINER_LIVE_BUSY: |
| 654 result += " container_busy=" + value; |
| 655 break; |
| 656 } |
| 657 } |
| 658 |
| 659 if (!children.empty()) |
| 660 result += " children=" + IntToString(children.size()); |
| 661 |
| 662 if (!indirect_child_ids.empty()) |
| 663 result += " indirect_child_ids=" + IntVectorToString(indirect_child_ids); |
| 664 |
| 665 if (!line_breaks.empty()) |
| 666 result += " line_breaks=" + IntVectorToString(line_breaks); |
| 667 |
| 668 if (!cell_ids.empty()) |
| 669 result += " cell_ids=" + IntVectorToString(cell_ids); |
| 670 |
| 671 if (recursive) { |
| 672 result += "\n"; |
| 673 ++indent; |
| 674 for (size_t i = 0; i < children.size(); ++i) |
| 675 result += children[i].DebugString(true); |
| 676 --indent; |
| 677 } |
| 678 |
| 679 return result; |
| 680 } |
| 681 #endif // ifndef NDEBUG |
| 682 |
312 void WebAccessibility::Init(const WebKit::WebAccessibilityObject& src, | 683 void WebAccessibility::Init(const WebKit::WebAccessibilityObject& src, |
313 WebKit::WebAccessibilityCache* cache, | 684 WebKit::WebAccessibilityCache* cache, |
314 bool include_children) { | 685 bool include_children) { |
315 name = src.title(); | 686 name = src.title(); |
316 value = src.stringValue(); | |
317 role = ConvertRole(src.roleValue()); | 687 role = ConvertRole(src.roleValue()); |
318 state = ConvertState(src); | 688 state = ConvertState(src); |
319 location = src.boundingBoxRect(); | 689 location = src.boundingBoxRect(); |
320 | 690 |
| 691 if (src.valueDescription().length()) |
| 692 value = src.valueDescription(); |
| 693 else |
| 694 value = src.stringValue(); |
| 695 |
| 696 if (src.accessKey().length()) |
| 697 string_attributes[ATTR_ACCESS_KEY] = src.accessKey(); |
321 if (src.actionVerb().length()) | 698 if (src.actionVerb().length()) |
322 string_attributes[ATTR_ACTION] = src.actionVerb(); | 699 string_attributes[ATTR_ACTION] = src.actionVerb(); |
| 700 if (src.isButtonStateMixed()) |
| 701 bool_attributes[ATTR_BUTTON_MIXED] = true; |
323 if (src.accessibilityDescription().length()) | 702 if (src.accessibilityDescription().length()) |
324 string_attributes[ATTR_DESCRIPTION] = src.accessibilityDescription(); | 703 string_attributes[ATTR_DESCRIPTION] = src.accessibilityDescription(); |
| 704 if (src.hasComputedStyle()) |
| 705 string_attributes[ATTR_DISPLAY] = src.computedStyleDisplay(); |
325 if (src.helpText().length()) | 706 if (src.helpText().length()) |
326 string_attributes[ATTR_HELP] = src.helpText(); | 707 string_attributes[ATTR_HELP] = src.helpText(); |
327 if (src.keyboardShortcut().length()) | 708 if (src.keyboardShortcut().length()) |
328 string_attributes[ATTR_SHORTCUT] = src.keyboardShortcut(); | 709 string_attributes[ATTR_SHORTCUT] = src.keyboardShortcut(); |
329 if (src.hasComputedStyle()) | |
330 string_attributes[ATTR_DISPLAY] = src.computedStyleDisplay(); | |
331 if (!src.url().isEmpty()) | 710 if (!src.url().isEmpty()) |
332 string_attributes[ATTR_URL] = src.url().spec().utf16(); | 711 string_attributes[ATTR_URL] = src.url().spec().utf16(); |
333 | 712 |
| 713 if (role == ROLE_TREE_ITEM) |
| 714 int_attributes[ATTR_HIERARCHICAL_LEVEL] = src.hierarchicalLevel(); |
| 715 |
| 716 if (role == ROLE_SLIDER) |
| 717 include_children = false; |
| 718 |
334 WebKit::WebNode node = src.node(); | 719 WebKit::WebNode node = src.node(); |
335 bool is_iframe = false; | 720 bool is_iframe = false; |
336 | 721 |
337 if (!node.isNull() && node.isElementNode()) { | 722 if (!node.isNull() && node.isElementNode()) { |
338 WebKit::WebElement element = node.to<WebKit::WebElement>(); | 723 WebKit::WebElement element = node.to<WebKit::WebElement>(); |
339 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); | 724 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); |
340 | 725 |
341 // TODO(ctguil): The tagName in WebKit is lower cased but | 726 // TODO(ctguil): The tagName in WebKit is lower cased but |
342 // HTMLElement::nodeName calls localNameUpper. Consider adding | 727 // HTMLElement::nodeName calls localNameUpper. Consider adding |
343 // a WebElement method that returns the original lower cased tagName. | 728 // a WebElement method that returns the original lower cased tagName. |
344 string_attributes[ATTR_HTML_TAG] = | 729 string_attributes[ATTR_HTML_TAG] = |
345 StringToLowerASCII(string16(element.tagName())); | 730 StringToLowerASCII(string16(element.tagName())); |
346 for (unsigned i = 0; i < element.attributes().length(); i++) { | 731 for (unsigned i = 0; i < element.attributes().length(); ++i) { |
347 html_attributes.push_back( | 732 string16 name = StringToLowerASCII(string16( |
348 std::pair<string16, string16>( | 733 element.attributes().attributeItem(i).localName())); |
349 element.attributes().attributeItem(i).localName(), | 734 string16 value = element.attributes().attributeItem(i).value(); |
350 element.attributes().attributeItem(i).value())); | 735 html_attributes.push_back(std::pair<string16, string16>(name, value)); |
351 } | 736 } |
352 | 737 |
353 if (element.isFormControlElement()) { | 738 if (element.isFormControlElement()) { |
354 WebKit::WebFormControlElement form_element = | 739 WebKit::WebFormControlElement form_element = |
355 element.to<WebKit::WebFormControlElement>(); | 740 element.to<WebKit::WebFormControlElement>(); |
356 if (form_element.formControlType() == ASCIIToUTF16("text") || | 741 if (form_element.formControlType() == ASCIIToUTF16("text") || |
357 form_element.formControlType() == ASCIIToUTF16("textarea")) { | 742 form_element.formControlType() == ASCIIToUTF16("textarea")) { |
358 // Jaws gets confused by children of text fields, so we ignore them. | 743 // Jaws gets confused by children of text fields, so we ignore them. |
359 include_children = false; | 744 include_children = false; |
360 | 745 |
361 int_attributes[ATTR_TEXT_SEL_START] = src.selectionStart(); | 746 int_attributes[ATTR_TEXT_SEL_START] = src.selectionStart(); |
362 int_attributes[ATTR_TEXT_SEL_END] = src.selectionEnd(); | 747 int_attributes[ATTR_TEXT_SEL_END] = src.selectionEnd(); |
363 WebKit::WebVector<int> src_line_breaks; | 748 WebKit::WebVector<int> src_line_breaks; |
364 src.lineBreaks(src_line_breaks); | 749 src.lineBreaks(src_line_breaks); |
365 line_breaks.reserve(src_line_breaks.size()); | 750 line_breaks.reserve(src_line_breaks.size()); |
366 for (size_t i = 0; i < src_line_breaks.size(); i++) | 751 for (size_t i = 0; i < src_line_breaks.size(); ++i) |
367 line_breaks.push_back(src_line_breaks[i]); | 752 line_breaks.push_back(src_line_breaks[i]); |
368 } | 753 } |
369 } | 754 } |
| 755 |
| 756 // ARIA role. |
| 757 if (element.hasAttribute("role")) { |
| 758 string_attributes[ATTR_ROLE] = element.getAttribute("role"); |
| 759 } |
| 760 |
| 761 // Live region attributes |
| 762 if (element.hasAttribute("aria-atomic")) { |
| 763 bool_attributes[ATTR_LIVE_ATOMIC] = |
| 764 LowerCaseEqualsASCII(element.getAttribute("aria-atomic"), "true"); |
| 765 } |
| 766 if (element.hasAttribute("aria-busy")) { |
| 767 bool_attributes[ATTR_LIVE_BUSY] = |
| 768 LowerCaseEqualsASCII(element.getAttribute("aria-busy"), "true"); |
| 769 } |
| 770 if (element.hasAttribute("aria-live")) { |
| 771 string_attributes[ATTR_LIVE_STATUS] = element.getAttribute("aria-live"); |
| 772 } |
| 773 if (element.hasAttribute("aria-relevant")) { |
| 774 string_attributes[ATTR_LIVE_RELEVANT] = |
| 775 element.getAttribute("aria-relevant"); |
| 776 } |
| 777 } |
| 778 |
| 779 // Walk up the parent chain to set live region attributes of containers |
| 780 |
| 781 WebKit::WebAccessibilityObject container_accessible = src; |
| 782 while (!container_accessible.isNull()) { |
| 783 WebKit::WebNode container_node = container_accessible.node(); |
| 784 if (!container_node.isNull() && container_node.isElementNode()) { |
| 785 WebKit::WebElement container_elem = |
| 786 container_node.to<WebKit::WebElement>(); |
| 787 if (container_elem.hasAttribute("aria-atomic") && |
| 788 bool_attributes.find(ATTR_CONTAINER_LIVE_ATOMIC) == |
| 789 bool_attributes.end()) { |
| 790 bool_attributes[ATTR_CONTAINER_LIVE_ATOMIC] = |
| 791 LowerCaseEqualsASCII(container_elem.getAttribute("aria-atomic"), |
| 792 "true"); |
| 793 } |
| 794 if (container_elem.hasAttribute("aria-busy") && |
| 795 bool_attributes.find(ATTR_CONTAINER_LIVE_BUSY) == |
| 796 bool_attributes.end()) { |
| 797 bool_attributes[ATTR_CONTAINER_LIVE_BUSY] = |
| 798 LowerCaseEqualsASCII(container_elem.getAttribute("aria-busy"), |
| 799 "true"); |
| 800 } |
| 801 if (container_elem.hasAttribute("aria-live") && |
| 802 string_attributes.find(ATTR_CONTAINER_LIVE_STATUS) == |
| 803 string_attributes.end()) { |
| 804 string_attributes[ATTR_CONTAINER_LIVE_STATUS] = |
| 805 container_elem.getAttribute("aria-live"); |
| 806 } |
| 807 if (container_elem.hasAttribute("aria-relevant") && |
| 808 string_attributes.find(ATTR_CONTAINER_LIVE_RELEVANT) == |
| 809 string_attributes.end()) { |
| 810 string_attributes[ATTR_CONTAINER_LIVE_RELEVANT] = |
| 811 container_elem.getAttribute("aria-relevant"); |
| 812 } |
| 813 } |
| 814 container_accessible = container_accessible.parentObject(); |
| 815 } |
| 816 |
| 817 if (role == WebAccessibility::ROLE_PROGRESS_INDICATOR || |
| 818 role == WebAccessibility::ROLE_SCROLLBAR || |
| 819 role == WebAccessibility::ROLE_SLIDER) { |
| 820 float_attributes[ATTR_VALUE_FOR_RANGE] = src.valueForRange(); |
| 821 float_attributes[ATTR_MAX_VALUE_FOR_RANGE] = src.minValueForRange(); |
| 822 float_attributes[ATTR_MIN_VALUE_FOR_RANGE] = src.maxValueForRange(); |
370 } | 823 } |
371 | 824 |
372 if (role == WebAccessibility::ROLE_DOCUMENT || | 825 if (role == WebAccessibility::ROLE_DOCUMENT || |
373 role == WebAccessibility::ROLE_WEB_AREA) { | 826 role == WebAccessibility::ROLE_WEB_AREA) { |
374 const WebKit::WebDocument& document = src.document(); | 827 const WebKit::WebDocument& document = src.document(); |
375 if (name.empty()) | 828 if (name.empty()) |
376 name = document.title(); | 829 name = document.title(); |
377 string_attributes[ATTR_DOC_TITLE] = document.title(); | 830 string_attributes[ATTR_DOC_TITLE] = document.title(); |
378 string_attributes[ATTR_DOC_URL] = document.url().spec().utf16(); | 831 string_attributes[ATTR_DOC_URL] = document.url().spec().utf16(); |
379 if (document.isXHTMLDocument()) | 832 if (document.isXHTMLDocument()) |
380 string_attributes[ATTR_DOC_MIMETYPE] = WebKit::WebString("text/xhtml"); | 833 string_attributes[ATTR_DOC_MIMETYPE] = WebKit::WebString("text/xhtml"); |
381 else | 834 else |
382 string_attributes[ATTR_DOC_MIMETYPE] = WebKit::WebString("text/html"); | 835 string_attributes[ATTR_DOC_MIMETYPE] = WebKit::WebString("text/html"); |
| 836 bool_attributes[ATTR_DOC_LOADED] = src.isLoaded(); |
| 837 float_attributes[ATTR_DOC_LOADING_PROGRESS] = |
| 838 src.estimatedLoadingProgress(); |
383 | 839 |
384 const WebKit::WebDocumentType& doctype = document.doctype(); | 840 const WebKit::WebDocumentType& doctype = document.doctype(); |
385 if (!doctype.isNull()) | 841 if (!doctype.isNull()) |
386 string_attributes[ATTR_DOC_DOCTYPE] = doctype.name(); | 842 string_attributes[ATTR_DOC_DOCTYPE] = doctype.name(); |
387 | 843 |
388 const gfx::Size& scroll_offset = document.frame()->scrollOffset(); | 844 const gfx::Size& scroll_offset = document.frame()->scrollOffset(); |
389 int_attributes[ATTR_DOC_SCROLLX] = scroll_offset.width(); | 845 int_attributes[ATTR_DOC_SCROLLX] = scroll_offset.width(); |
390 int_attributes[ATTR_DOC_SCROLLY] = scroll_offset.height(); | 846 int_attributes[ATTR_DOC_SCROLLY] = scroll_offset.height(); |
391 } | 847 } |
392 | 848 |
393 if (role == WebAccessibility::ROLE_TABLE) { | 849 if (role == WebAccessibility::ROLE_TABLE) { |
394 int column_count = src.columnCount(); | 850 int column_count = src.columnCount(); |
395 int row_count = src.rowCount(); | 851 int row_count = src.rowCount(); |
396 if (column_count > 0 && row_count > 0) { | 852 if (column_count > 0 && row_count > 0) { |
| 853 std::set<int> unique_cell_id_set; |
397 int_attributes[ATTR_TABLE_COLUMN_COUNT] = column_count; | 854 int_attributes[ATTR_TABLE_COLUMN_COUNT] = column_count; |
398 int_attributes[ATTR_TABLE_ROW_COUNT] = row_count; | 855 int_attributes[ATTR_TABLE_ROW_COUNT] = row_count; |
399 for (int i = 0; i < column_count * row_count; i++) { | 856 for (int i = 0; i < column_count * row_count; ++i) { |
400 WebAccessibilityObject cell = src.cellForColumnAndRow( | 857 WebAccessibilityObject cell = src.cellForColumnAndRow( |
401 i % column_count, i / column_count); | 858 i % column_count, i / column_count); |
402 int cell_id = -1; | 859 int cell_id = -1; |
403 if (!cell.isNull()) | 860 if (!cell.isNull()) { |
404 cell_id = cache->addOrGetId(cell); | 861 cell_id = cache->addOrGetId(cell); |
| 862 if (unique_cell_id_set.find(cell_id) == unique_cell_id_set.end()) { |
| 863 unique_cell_id_set.insert(cell_id); |
| 864 unique_cell_ids.push_back(cell_id); |
| 865 } |
| 866 } |
405 cell_ids.push_back(cell_id); | 867 cell_ids.push_back(cell_id); |
406 } | 868 } |
407 } | 869 } |
408 } | 870 } |
409 | 871 |
410 if (role == WebAccessibility::ROLE_CELL || | 872 if (role == WebAccessibility::ROLE_CELL || |
411 role == WebAccessibility::ROLE_ROW_HEADER || | 873 role == WebAccessibility::ROLE_ROW_HEADER || |
412 role == WebAccessibility::ROLE_COLUMN_HEADER) { | 874 role == WebAccessibility::ROLE_COLUMN_HEADER) { |
413 int_attributes[ATTR_TABLE_CELL_COLUMN_INDEX] = src.cellColumnIndex(); | 875 int_attributes[ATTR_TABLE_CELL_COLUMN_INDEX] = src.cellColumnIndex(); |
414 int_attributes[ATTR_TABLE_CELL_COLUMN_SPAN] = src.cellColumnSpan(); | 876 int_attributes[ATTR_TABLE_CELL_COLUMN_SPAN] = src.cellColumnSpan(); |
415 int_attributes[ATTR_TABLE_CELL_ROW_INDEX] = src.cellRowIndex(); | 877 int_attributes[ATTR_TABLE_CELL_ROW_INDEX] = src.cellRowIndex(); |
416 int_attributes[ATTR_TABLE_CELL_ROW_SPAN] = src.cellRowSpan(); | 878 int_attributes[ATTR_TABLE_CELL_ROW_SPAN] = src.cellRowSpan(); |
417 } | 879 } |
418 | 880 |
419 // Add the source object to the cache and store its id. | 881 // Add the source object to the cache and store its id. |
420 id = cache->addOrGetId(src); | 882 id = cache->addOrGetId(src); |
421 | 883 |
422 if (include_children) { | 884 if (include_children) { |
423 // Recursively create children. | 885 // Recursively create children. |
424 int child_count = src.childCount(); | 886 int child_count = src.childCount(); |
425 std::set<int32> child_ids; | 887 std::set<int32> child_ids; |
426 for (int i = 0; i < child_count; i++) { | 888 for (int i = 0; i < child_count; ++i) { |
427 WebAccessibilityObject child = src.childAt(i); | 889 WebAccessibilityObject child = src.childAt(i); |
428 int32 child_id = cache->addOrGetId(child); | 890 int32 child_id = cache->addOrGetId(child); |
429 | 891 |
430 // The child may be invalid due to issues in webkit accessibility code. | 892 // The child may be invalid due to issues in webkit accessibility code. |
431 // Don't add children that are invalid thus preventing a crash. | 893 // Don't add children that are invalid thus preventing a crash. |
432 // https://bugs.webkit.org/show_bug.cgi?id=44149 | 894 // https://bugs.webkit.org/show_bug.cgi?id=44149 |
433 // TODO(ctguil): We may want to remove this check as webkit stabilizes. | 895 // TODO(ctguil): We may want to remove this check as webkit stabilizes. |
434 if (!child.isValid()) | 896 if (!child.isValid()) |
435 continue; | 897 continue; |
436 | 898 |
(...skipping 24 matching lines...) Expand all Loading... |
461 bool WebAccessibility::IsParentUnignoredOf( | 923 bool WebAccessibility::IsParentUnignoredOf( |
462 const WebKit::WebAccessibilityObject& ancestor, | 924 const WebKit::WebAccessibilityObject& ancestor, |
463 const WebKit::WebAccessibilityObject& child) { | 925 const WebKit::WebAccessibilityObject& child) { |
464 WebKit::WebAccessibilityObject parent = child.parentObject(); | 926 WebKit::WebAccessibilityObject parent = child.parentObject(); |
465 while (!parent.isNull() && parent.accessibilityIsIgnored()) | 927 while (!parent.isNull() && parent.accessibilityIsIgnored()) |
466 parent = parent.parentObject(); | 928 parent = parent.parentObject(); |
467 return parent.equals(ancestor); | 929 return parent.equals(ancestor); |
468 } | 930 } |
469 | 931 |
470 } // namespace webkit_glue | 932 } // namespace webkit_glue |
OLD | NEW |