Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(206)

Side by Side Diff: content/renderer/accessibility/blink_ax_tree_source.cc

Issue 2581483002: Add support for faster, more limited accessibility modes. (Closed)
Patch Set: Disable tests that can't pass on Android with TODO Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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 "content/renderer/accessibility/blink_ax_tree_source.h" 5 #include "content/renderer/accessibility/blink_ax_tree_source.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <set> 9 #include <set>
10 10
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 ScopedFreezeBlinkAXTreeSource::ScopedFreezeBlinkAXTreeSource( 121 ScopedFreezeBlinkAXTreeSource::ScopedFreezeBlinkAXTreeSource(
122 BlinkAXTreeSource* tree_source) 122 BlinkAXTreeSource* tree_source)
123 : tree_source_(tree_source) { 123 : tree_source_(tree_source) {
124 tree_source_->Freeze(); 124 tree_source_->Freeze();
125 } 125 }
126 126
127 ScopedFreezeBlinkAXTreeSource::~ScopedFreezeBlinkAXTreeSource() { 127 ScopedFreezeBlinkAXTreeSource::~ScopedFreezeBlinkAXTreeSource() {
128 tree_source_->Thaw(); 128 tree_source_->Thaw();
129 } 129 }
130 130
131 BlinkAXTreeSource::BlinkAXTreeSource(RenderFrameImpl* render_frame) 131 BlinkAXTreeSource::BlinkAXTreeSource(RenderFrameImpl* render_frame,
132 AccessibilityMode mode)
132 : render_frame_(render_frame), 133 : render_frame_(render_frame),
134 accessibility_mode_(mode),
133 frozen_(false) {} 135 frozen_(false) {}
134 136
135 BlinkAXTreeSource::~BlinkAXTreeSource() { 137 BlinkAXTreeSource::~BlinkAXTreeSource() {
136 } 138 }
137 139
138 void BlinkAXTreeSource::Freeze() { 140 void BlinkAXTreeSource::Freeze() {
139 CHECK(!frozen_); 141 CHECK(!frozen_);
140 frozen_ = true; 142 frozen_ = true;
141 143
142 if (render_frame_ && render_frame_->GetWebFrame()) 144 if (render_frame_ && render_frame_->GetWebFrame())
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 blink::WebString web_description = src.description( 336 blink::WebString web_description = src.description(
335 nameFrom, descriptionFrom, descriptionObjects); 337 nameFrom, descriptionFrom, descriptionObjects);
336 if (!web_description.isEmpty()) { 338 if (!web_description.isEmpty()) {
337 dst->AddStringAttribute(ui::AX_ATTR_DESCRIPTION, web_description.utf8()); 339 dst->AddStringAttribute(ui::AX_ATTR_DESCRIPTION, web_description.utf8());
338 dst->AddIntAttribute(ui::AX_ATTR_DESCRIPTION_FROM, 340 dst->AddIntAttribute(ui::AX_ATTR_DESCRIPTION_FROM,
339 AXDescriptionFromFromBlink(descriptionFrom)); 341 AXDescriptionFromFromBlink(descriptionFrom));
340 AddIntListAttributeFromWebObjects( 342 AddIntListAttributeFromWebObjects(
341 ui::AX_ATTR_DESCRIBEDBY_IDS, descriptionObjects, dst); 343 ui::AX_ATTR_DESCRIBEDBY_IDS, descriptionObjects, dst);
342 } 344 }
343 345
344 blink::WebString web_placeholder = src.placeholder(nameFrom);
345 if (!web_placeholder.isEmpty())
346 dst->AddStringAttribute(ui::AX_ATTR_PLACEHOLDER, web_placeholder.utf8());
347
348 std::string value; 346 std::string value;
349 if (src.valueDescription().length()) { 347 if (src.valueDescription().length()) {
350 dst->AddStringAttribute(ui::AX_ATTR_VALUE, src.valueDescription().utf8()); 348 dst->AddStringAttribute(ui::AX_ATTR_VALUE, src.valueDescription().utf8());
351 } else { 349 } else {
352 dst->AddStringAttribute(ui::AX_ATTR_VALUE, src.stringValue().utf8()); 350 dst->AddStringAttribute(ui::AX_ATTR_VALUE, src.stringValue().utf8());
353 } 351 }
354 352
355 if (dst->role == ui::AX_ROLE_COLOR_WELL)
356 dst->AddIntAttribute(ui::AX_ATTR_COLOR_VALUE, src.colorValue());
357
358
359 // Text attributes.
360 if (src.backgroundColor())
361 dst->AddIntAttribute(ui::AX_ATTR_BACKGROUND_COLOR, src.backgroundColor());
362
363 if (src.color())
364 dst->AddIntAttribute(ui::AX_ATTR_COLOR, src.color());
365
366 WebAXObject parent = ParentObjectUnignored(src);
367 if (src.fontFamily().length()) {
368 if (parent.isNull() || parent.fontFamily() != src.fontFamily())
369 dst->AddStringAttribute(ui::AX_ATTR_FONT_FAMILY, src.fontFamily().utf8());
370 }
371
372 // Font size is in pixels.
373 if (src.fontSize())
374 dst->AddFloatAttribute(ui::AX_ATTR_FONT_SIZE, src.fontSize());
375
376 if (src.ariaCurrentState()) {
377 dst->AddIntAttribute(ui::AX_ATTR_ARIA_CURRENT_STATE,
378 AXAriaCurrentStateFromBlink(src.ariaCurrentState()));
379 }
380
381 if (src.invalidState()) {
382 dst->AddIntAttribute(ui::AX_ATTR_INVALID_STATE,
383 AXInvalidStateFromBlink(src.invalidState()));
384 }
385 if (src.invalidState() == blink::WebAXInvalidStateOther &&
386 src.ariaInvalidValue().length()) {
387 dst->AddStringAttribute(
388 ui::AX_ATTR_ARIA_INVALID_VALUE, src.ariaInvalidValue().utf8());
389 }
390
391 if (src.textDirection()) {
392 dst->AddIntAttribute(ui::AX_ATTR_TEXT_DIRECTION,
393 AXTextDirectionFromBlink(src.textDirection()));
394 }
395
396 if (src.textStyle()) {
397 dst->AddIntAttribute(ui::AX_ATTR_TEXT_STYLE,
398 AXTextStyleFromBlink(src.textStyle()));
399 }
400
401
402 if (dst->role == ui::AX_ROLE_INLINE_TEXT_BOX) {
403 WebVector<int> src_character_offsets;
404 src.characterOffsets(src_character_offsets);
405 std::vector<int32_t> character_offsets;
406 character_offsets.reserve(src_character_offsets.size());
407 for (size_t i = 0; i < src_character_offsets.size(); ++i)
408 character_offsets.push_back(src_character_offsets[i]);
409 dst->AddIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS, character_offsets);
410
411 WebVector<int> src_word_starts;
412 WebVector<int> src_word_ends;
413 src.wordBoundaries(src_word_starts, src_word_ends);
414 std::vector<int32_t> word_starts;
415 std::vector<int32_t> word_ends;
416 word_starts.reserve(src_word_starts.size());
417 word_ends.reserve(src_word_starts.size());
418 for (size_t i = 0; i < src_word_starts.size(); ++i) {
419 word_starts.push_back(src_word_starts[i]);
420 word_ends.push_back(src_word_ends[i]);
421 }
422 dst->AddIntListAttribute(ui::AX_ATTR_WORD_STARTS, word_starts);
423 dst->AddIntListAttribute(ui::AX_ATTR_WORD_ENDS, word_ends);
424 }
425
426 if (src.accessKey().length()) {
427 dst->AddStringAttribute(ui::AX_ATTR_ACCESS_KEY, src.accessKey().utf8());
428 }
429
430 if (src.action() != blink::WebAXSupportedAction::None) {
431 dst->AddIntAttribute(ui::AX_ATTR_ACTION,
432 AXSupportedActionFromBlink(src.action()));
433 }
434
435 if (src.ariaAutoComplete().length()) {
436 dst->AddStringAttribute(
437 ui::AX_ATTR_AUTO_COMPLETE,
438 src.ariaAutoComplete().utf8());
439 }
440
441 if (src.isAriaReadOnly())
442 dst->AddBoolAttribute(ui::AX_ATTR_ARIA_READONLY, true);
443
444 if (src.isButtonStateMixed()) 353 if (src.isButtonStateMixed())
445 dst->AddBoolAttribute(ui::AX_ATTR_STATE_MIXED, true); 354 dst->AddBoolAttribute(ui::AX_ATTR_STATE_MIXED, true);
446 355
447 if (src.canSetValueAttribute()) 356 if (src.canSetValueAttribute())
448 dst->AddBoolAttribute(ui::AX_ATTR_CAN_SET_VALUE, true); 357 dst->AddBoolAttribute(ui::AX_ATTR_CAN_SET_VALUE, true);
449 358
450 if (src.hasComputedStyle()) {
451 dst->AddStringAttribute(
452 ui::AX_ATTR_DISPLAY, src.computedStyleDisplay().utf8());
453 }
454
455 if (src.language().length()) {
456 if (parent.isNull() || parent.language() != src.language())
457 dst->AddStringAttribute(ui::AX_ATTR_LANGUAGE, src.language().utf8());
458 }
459
460 if (src.keyboardShortcut().length()) {
461 dst->AddStringAttribute(
462 ui::AX_ATTR_SHORTCUT,
463 src.keyboardShortcut().utf8());
464 }
465
466 if (!src.nextOnLine().isDetached()) {
467 dst->AddIntAttribute(ui::AX_ATTR_NEXT_ON_LINE_ID, src.nextOnLine().axID());
468 }
469
470 if (!src.previousOnLine().isDetached()) {
471 dst->AddIntAttribute(ui::AX_ATTR_PREVIOUS_ON_LINE_ID,
472 src.previousOnLine().axID());
473 }
474
475 if (!src.ariaActiveDescendant().isDetached()) {
476 dst->AddIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID,
477 src.ariaActiveDescendant().axID());
478 }
479
480 if (!src.url().isEmpty()) 359 if (!src.url().isEmpty())
481 dst->AddStringAttribute(ui::AX_ATTR_URL, src.url().string().utf8()); 360 dst->AddStringAttribute(ui::AX_ATTR_URL, src.url().string().utf8());
482 361
483 if (dst->role == ui::AX_ROLE_HEADING && src.headingLevel()) { 362 // The following set of attributes are only accessed when the accessibility
484 dst->AddIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL, src.headingLevel()); 363 // mode is set to screen reader mode, otherwise only the more basic
485 } else if ((dst->role == ui::AX_ROLE_TREE_ITEM || 364 // attributes are populated.
486 dst->role == ui::AX_ROLE_ROW) && 365 if (accessibility_mode_ & ACCESSIBILITY_MODE_FLAG_SCREEN_READER) {
487 src.hierarchicalLevel()) { 366 blink::WebString web_placeholder = src.placeholder(nameFrom);
488 dst->AddIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL, 367 if (!web_placeholder.isEmpty())
489 src.hierarchicalLevel()); 368 dst->AddStringAttribute(ui::AX_ATTR_PLACEHOLDER, web_placeholder.utf8());
369
370 if (dst->role == ui::AX_ROLE_COLOR_WELL)
371 dst->AddIntAttribute(ui::AX_ATTR_COLOR_VALUE, src.colorValue());
372
373 // Text attributes.
374 if (src.backgroundColor())
375 dst->AddIntAttribute(ui::AX_ATTR_BACKGROUND_COLOR, src.backgroundColor());
376
377 if (src.color())
378 dst->AddIntAttribute(ui::AX_ATTR_COLOR, src.color());
379
380 WebAXObject parent = ParentObjectUnignored(src);
381 if (src.fontFamily().length()) {
382 if (parent.isNull() || parent.fontFamily() != src.fontFamily())
383 dst->AddStringAttribute(ui::AX_ATTR_FONT_FAMILY,
384 src.fontFamily().utf8());
385 }
386
387 // Font size is in pixels.
388 if (src.fontSize())
389 dst->AddFloatAttribute(ui::AX_ATTR_FONT_SIZE, src.fontSize());
390
391 if (src.ariaCurrentState()) {
392 dst->AddIntAttribute(ui::AX_ATTR_ARIA_CURRENT_STATE,
393 AXAriaCurrentStateFromBlink(src.ariaCurrentState()));
394 }
395
396 if (src.invalidState()) {
397 dst->AddIntAttribute(ui::AX_ATTR_INVALID_STATE,
398 AXInvalidStateFromBlink(src.invalidState()));
399 }
400 if (src.invalidState() == blink::WebAXInvalidStateOther &&
401 src.ariaInvalidValue().length()) {
402 dst->AddStringAttribute(
403 ui::AX_ATTR_ARIA_INVALID_VALUE, src.ariaInvalidValue().utf8());
404 }
405
406 if (src.textDirection()) {
407 dst->AddIntAttribute(ui::AX_ATTR_TEXT_DIRECTION,
408 AXTextDirectionFromBlink(src.textDirection()));
409 }
410
411 if (src.textStyle()) {
412 dst->AddIntAttribute(ui::AX_ATTR_TEXT_STYLE,
413 AXTextStyleFromBlink(src.textStyle()));
414 }
415
416 if (dst->role == ui::AX_ROLE_INLINE_TEXT_BOX) {
417 WebVector<int> src_character_offsets;
418 src.characterOffsets(src_character_offsets);
419 std::vector<int32_t> character_offsets;
420 character_offsets.reserve(src_character_offsets.size());
421 for (size_t i = 0; i < src_character_offsets.size(); ++i)
422 character_offsets.push_back(src_character_offsets[i]);
423 dst->AddIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS,
424 character_offsets);
425
426 WebVector<int> src_word_starts;
427 WebVector<int> src_word_ends;
428 src.wordBoundaries(src_word_starts, src_word_ends);
429 std::vector<int32_t> word_starts;
430 std::vector<int32_t> word_ends;
431 word_starts.reserve(src_word_starts.size());
432 word_ends.reserve(src_word_starts.size());
433 for (size_t i = 0; i < src_word_starts.size(); ++i) {
434 word_starts.push_back(src_word_starts[i]);
435 word_ends.push_back(src_word_ends[i]);
436 }
437 dst->AddIntListAttribute(ui::AX_ATTR_WORD_STARTS, word_starts);
438 dst->AddIntListAttribute(ui::AX_ATTR_WORD_ENDS, word_ends);
439 }
440
441 if (src.accessKey().length()) {
442 dst->AddStringAttribute(ui::AX_ATTR_ACCESS_KEY, src.accessKey().utf8());
443 }
444
445 if (src.ariaAutoComplete().length()) {
446 dst->AddStringAttribute(
447 ui::AX_ATTR_AUTO_COMPLETE,
448 src.ariaAutoComplete().utf8());
449 }
450
451 if (src.action() != blink::WebAXSupportedAction::None) {
452 dst->AddIntAttribute(ui::AX_ATTR_ACTION,
453 AXSupportedActionFromBlink(src.action()));
454 }
455
456 if (src.isAriaReadOnly())
457 dst->AddBoolAttribute(ui::AX_ATTR_ARIA_READONLY, true);
458
459 if (src.hasComputedStyle()) {
460 dst->AddStringAttribute(
461 ui::AX_ATTR_DISPLAY, src.computedStyleDisplay().utf8());
462 }
463
464 if (src.language().length()) {
465 if (parent.isNull() || parent.language() != src.language())
466 dst->AddStringAttribute(ui::AX_ATTR_LANGUAGE, src.language().utf8());
467 }
468
469 if (src.keyboardShortcut().length()) {
470 dst->AddStringAttribute(
471 ui::AX_ATTR_SHORTCUT,
472 src.keyboardShortcut().utf8());
473 }
474
475 if (!src.nextOnLine().isDetached()) {
476 dst->AddIntAttribute(ui::AX_ATTR_NEXT_ON_LINE_ID,
477 src.nextOnLine().axID());
478 }
479
480 if (!src.previousOnLine().isDetached()) {
481 dst->AddIntAttribute(ui::AX_ATTR_PREVIOUS_ON_LINE_ID,
482 src.previousOnLine().axID());
483 }
484
485 if (!src.ariaActiveDescendant().isDetached()) {
486 dst->AddIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID,
487 src.ariaActiveDescendant().axID());
488 }
489
490 if (dst->role == ui::AX_ROLE_HEADING && src.headingLevel()) {
491 dst->AddIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL, src.headingLevel());
492 } else if ((dst->role == ui::AX_ROLE_TREE_ITEM ||
493 dst->role == ui::AX_ROLE_ROW) &&
494 src.hierarchicalLevel()) {
495 dst->AddIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL,
496 src.hierarchicalLevel());
497 }
498
499 if (src.setSize())
500 dst->AddIntAttribute(ui::AX_ATTR_SET_SIZE, src.setSize());
501
502 if (src.posInSet())
503 dst->AddIntAttribute(ui::AX_ATTR_POS_IN_SET, src.posInSet());
504
505 if (src.canvasHasFallbackContent())
506 dst->AddBoolAttribute(ui::AX_ATTR_CANVAS_HAS_FALLBACK, true);
507
508 // Spelling, grammar and other document markers.
509 WebVector<blink::WebAXMarkerType> src_marker_types;
510 WebVector<int> src_marker_starts;
511 WebVector<int> src_marker_ends;
512 src.markers(src_marker_types, src_marker_starts, src_marker_ends);
513 DCHECK_EQ(src_marker_types.size(), src_marker_starts.size());
514 DCHECK_EQ(src_marker_starts.size(), src_marker_ends.size());
515
516 if (src_marker_types.size()) {
517 std::vector<int32_t> marker_types;
518 std::vector<int32_t> marker_starts;
519 std::vector<int32_t> marker_ends;
520 marker_types.reserve(src_marker_types.size());
521 marker_starts.reserve(src_marker_starts.size());
522 marker_ends.reserve(src_marker_ends.size());
523 for (size_t i = 0; i < src_marker_types.size(); ++i) {
524 marker_types.push_back(
525 static_cast<int32_t>(AXMarkerTypeFromBlink(src_marker_types[i])));
526 marker_starts.push_back(src_marker_starts[i]);
527 marker_ends.push_back(src_marker_ends[i]);
528 }
529 dst->AddIntListAttribute(ui::AX_ATTR_MARKER_TYPES, marker_types);
530 dst->AddIntListAttribute(ui::AX_ATTR_MARKER_STARTS, marker_starts);
531 dst->AddIntListAttribute(ui::AX_ATTR_MARKER_ENDS, marker_ends);
532 }
533
534 if (src.isInLiveRegion()) {
535 dst->AddBoolAttribute(ui::AX_ATTR_LIVE_ATOMIC, src.liveRegionAtomic());
536 dst->AddBoolAttribute(ui::AX_ATTR_LIVE_BUSY, src.liveRegionBusy());
537 if (src.liveRegionBusy())
538 dst->state |= (1 << ui::AX_STATE_BUSY);
539 if (!src.liveRegionStatus().isEmpty()) {
540 dst->AddStringAttribute(
541 ui::AX_ATTR_LIVE_STATUS,
542 src.liveRegionStatus().utf8());
543 }
544 dst->AddStringAttribute(
545 ui::AX_ATTR_LIVE_RELEVANT,
546 src.liveRegionRelevant().utf8());
547 // If we are not at the root of an atomic live region.
548 if (src.containerLiveRegionAtomic() &&
549 !src.liveRegionRoot().isDetached() &&
550 !src.liveRegionAtomic()) {
551 dst->AddIntAttribute(ui::AX_ATTR_MEMBER_OF_ID,
552 src.liveRegionRoot().axID());
553 }
554 dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_ATOMIC,
555 src.containerLiveRegionAtomic());
556 dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY,
557 src.containerLiveRegionBusy());
558 dst->AddStringAttribute(
559 ui::AX_ATTR_CONTAINER_LIVE_STATUS,
560 src.containerLiveRegionStatus().utf8());
561 dst->AddStringAttribute(
562 ui::AX_ATTR_CONTAINER_LIVE_RELEVANT,
563 src.containerLiveRegionRelevant().utf8());
564 }
565
566 if (dst->role == ui::AX_ROLE_PROGRESS_INDICATOR ||
567 dst->role == ui::AX_ROLE_METER ||
568 dst->role == ui::AX_ROLE_SCROLL_BAR ||
569 dst->role == ui::AX_ROLE_SLIDER ||
570 dst->role == ui::AX_ROLE_SPIN_BUTTON) {
571 dst->AddFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, src.valueForRange());
572 dst->AddFloatAttribute(ui::AX_ATTR_MAX_VALUE_FOR_RANGE,
573 src.maxValueForRange());
574 dst->AddFloatAttribute(ui::AX_ATTR_MIN_VALUE_FOR_RANGE,
575 src.minValueForRange());
576 }
577
578 if (dst->role == ui::AX_ROLE_ROOT_WEB_AREA)
579 dst->AddStringAttribute(ui::AX_ATTR_HTML_TAG, "#document");
580
581 if (dst->role == ui::AX_ROLE_TABLE) {
582 int column_count = src.columnCount();
583 int row_count = src.rowCount();
584 if (column_count > 0 && row_count > 0) {
585 std::set<int32_t> unique_cell_id_set;
586 std::vector<int32_t> cell_ids;
587 std::vector<int32_t> unique_cell_ids;
588 dst->AddIntAttribute(ui::AX_ATTR_TABLE_COLUMN_COUNT, column_count);
589 dst->AddIntAttribute(ui::AX_ATTR_TABLE_ROW_COUNT, row_count);
590 WebAXObject header = src.headerContainerObject();
591 if (!header.isDetached())
592 dst->AddIntAttribute(ui::AX_ATTR_TABLE_HEADER_ID, header.axID());
593 for (int i = 0; i < column_count * row_count; ++i) {
594 WebAXObject cell = src.cellForColumnAndRow(
595 i % column_count, i / column_count);
596 int cell_id = -1;
597 if (!cell.isDetached()) {
598 cell_id = cell.axID();
599 if (unique_cell_id_set.find(cell_id) == unique_cell_id_set.end()) {
600 unique_cell_id_set.insert(cell_id);
601 unique_cell_ids.push_back(cell_id);
602 }
603 }
604 cell_ids.push_back(cell_id);
605 }
606 dst->AddIntListAttribute(ui::AX_ATTR_CELL_IDS, cell_ids);
607 dst->AddIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS, unique_cell_ids);
608 }
609 }
610
611 if (dst->role == ui::AX_ROLE_ROW) {
612 dst->AddIntAttribute(ui::AX_ATTR_TABLE_ROW_INDEX, src.rowIndex());
613 WebAXObject header = src.rowHeader();
614 if (!header.isDetached())
615 dst->AddIntAttribute(ui::AX_ATTR_TABLE_ROW_HEADER_ID, header.axID());
616 }
617
618 if (dst->role == ui::AX_ROLE_COLUMN) {
619 dst->AddIntAttribute(ui::AX_ATTR_TABLE_COLUMN_INDEX, src.columnIndex());
620 WebAXObject header = src.columnHeader();
621 if (!header.isDetached())
622 dst->AddIntAttribute(ui::AX_ATTR_TABLE_COLUMN_HEADER_ID, header.axID());
623 }
624
625 if (dst->role == ui::AX_ROLE_CELL ||
626 dst->role == ui::AX_ROLE_ROW_HEADER ||
627 dst->role == ui::AX_ROLE_COLUMN_HEADER) {
628 dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_INDEX,
629 src.cellColumnIndex());
630 dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN,
631 src.cellColumnSpan());
632 dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_INDEX,
633 src.cellRowIndex());
634 dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_SPAN, src.cellRowSpan());
635 }
636
637 if ((dst->role == ui::AX_ROLE_ROW_HEADER ||
638 dst->role == ui::AX_ROLE_COLUMN_HEADER) && src.sortDirection()) {
639 dst->AddIntAttribute(ui::AX_ATTR_SORT_DIRECTION,
640 AXSortDirectionFromBlink(src.sortDirection()));
641 }
490 } 642 }
491 643
492 if (src.setSize()) 644 // The majority of the rest of this code computes attributes needed for
493 dst->AddIntAttribute(ui::AX_ATTR_SET_SIZE, src.setSize()); 645 // all modes, not just for screen readers.
494
495 if (src.posInSet())
496 dst->AddIntAttribute(ui::AX_ATTR_POS_IN_SET, src.posInSet());
497
498 if (src.canvasHasFallbackContent())
499 dst->AddBoolAttribute(ui::AX_ATTR_CANVAS_HAS_FALLBACK, true);
500
501 // Spelling, grammar and other document markers.
502 WebVector<blink::WebAXMarkerType> src_marker_types;
503 WebVector<int> src_marker_starts;
504 WebVector<int> src_marker_ends;
505 src.markers(src_marker_types, src_marker_starts, src_marker_ends);
506 DCHECK_EQ(src_marker_types.size(), src_marker_starts.size());
507 DCHECK_EQ(src_marker_starts.size(), src_marker_ends.size());
508
509 if (src_marker_types.size()) {
510 std::vector<int32_t> marker_types;
511 std::vector<int32_t> marker_starts;
512 std::vector<int32_t> marker_ends;
513 marker_types.reserve(src_marker_types.size());
514 marker_starts.reserve(src_marker_starts.size());
515 marker_ends.reserve(src_marker_ends.size());
516 for (size_t i = 0; i < src_marker_types.size(); ++i) {
517 marker_types.push_back(
518 static_cast<int32_t>(AXMarkerTypeFromBlink(src_marker_types[i])));
519 marker_starts.push_back(src_marker_starts[i]);
520 marker_ends.push_back(src_marker_ends[i]);
521 }
522 dst->AddIntListAttribute(ui::AX_ATTR_MARKER_TYPES, marker_types);
523 dst->AddIntListAttribute(ui::AX_ATTR_MARKER_STARTS, marker_starts);
524 dst->AddIntListAttribute(ui::AX_ATTR_MARKER_ENDS, marker_ends);
525 }
526 646
527 WebNode node = src.node(); 647 WebNode node = src.node();
528 bool is_iframe = false; 648 bool is_iframe = false;
529 649
530 if (!node.isNull() && node.isElementNode()) { 650 if (!node.isNull() && node.isElementNode()) {
531 WebElement element = node.to<WebElement>(); 651 WebElement element = node.to<WebElement>();
532 is_iframe = element.hasHTMLTagName("iframe"); 652 is_iframe = element.hasHTMLTagName("iframe");
533 653
534 // TODO(ctguil): The tagName in WebKit is lower cased but 654 if (accessibility_mode_ & ACCESSIBILITY_MODE_FLAG_HTML) {
535 // HTMLElement::nodeName calls localNameUpper. Consider adding 655 // TODO(ctguil): The tagName in WebKit is lower cased but
536 // a WebElement method that returns the original lower cased tagName. 656 // HTMLElement::nodeName calls localNameUpper. Consider adding
537 dst->AddStringAttribute( 657 // a WebElement method that returns the original lower cased tagName.
538 ui::AX_ATTR_HTML_TAG, 658 dst->AddStringAttribute(
539 base::ToLowerASCII(element.tagName().utf8())); 659 ui::AX_ATTR_HTML_TAG,
540 for (unsigned i = 0; i < element.attributeCount(); ++i) { 660 base::ToLowerASCII(element.tagName().utf8()));
541 std::string name = base::ToLowerASCII( 661 for (unsigned i = 0; i < element.attributeCount(); ++i) {
542 element.attributeLocalName(i).utf8()); 662 std::string name = base::ToLowerASCII(
543 std::string value = element.attributeValue(i).utf8(); 663 element.attributeLocalName(i).utf8());
544 dst->html_attributes.push_back(std::make_pair(name, value)); 664 std::string value = element.attributeValue(i).utf8();
665 dst->html_attributes.push_back(std::make_pair(name, value));
666 }
545 } 667 }
546 668
547 if (src.isEditable()) { 669 if (src.isEditable()) {
548 dst->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, src.selectionStart()); 670 dst->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, src.selectionStart());
549 dst->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_END, src.selectionEnd()); 671 dst->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_END, src.selectionEnd());
550 672
551 #if defined(OS_CHROMEOS) 673 #if defined(OS_CHROMEOS)
552 // This attribute will soon be deprecated; see crbug.com/669134. 674 // This attribute will soon be deprecated; see crbug.com/669134.
553 WebVector<int> src_line_breaks; 675 WebVector<int> src_line_breaks;
554 src.lineBreaks(src_line_breaks); 676 src.lineBreaks(src_line_breaks);
(...skipping 30 matching lines...) Expand all
585 707
586 // Frames and iframes. 708 // Frames and iframes.
587 WebFrame* frame = WebFrame::fromFrameOwnerElement(element); 709 WebFrame* frame = WebFrame::fromFrameOwnerElement(element);
588 if (frame) { 710 if (frame) {
589 dst->AddContentIntAttribute( 711 dst->AddContentIntAttribute(
590 AX_CONTENT_ATTR_CHILD_ROUTING_ID, 712 AX_CONTENT_ATTR_CHILD_ROUTING_ID,
591 GetRoutingIdForFrameOrProxy(frame)); 713 GetRoutingIdForFrameOrProxy(frame));
592 } 714 }
593 } 715 }
594 716
595 if (src.isInLiveRegion()) {
596 dst->AddBoolAttribute(ui::AX_ATTR_LIVE_ATOMIC, src.liveRegionAtomic());
597 dst->AddBoolAttribute(ui::AX_ATTR_LIVE_BUSY, src.liveRegionBusy());
598 if (src.liveRegionBusy())
599 dst->state |= (1 << ui::AX_STATE_BUSY);
600 if (!src.liveRegionStatus().isEmpty()) {
601 dst->AddStringAttribute(
602 ui::AX_ATTR_LIVE_STATUS,
603 src.liveRegionStatus().utf8());
604 }
605 dst->AddStringAttribute(
606 ui::AX_ATTR_LIVE_RELEVANT,
607 src.liveRegionRelevant().utf8());
608 // If we are not at the root of an atomic live region.
609 if (src.containerLiveRegionAtomic() && !src.liveRegionRoot().isDetached() &&
610 !src.liveRegionAtomic()) {
611 dst->AddIntAttribute(ui::AX_ATTR_MEMBER_OF_ID,
612 src.liveRegionRoot().axID());
613 }
614 dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_ATOMIC,
615 src.containerLiveRegionAtomic());
616 dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY,
617 src.containerLiveRegionBusy());
618 dst->AddStringAttribute(
619 ui::AX_ATTR_CONTAINER_LIVE_STATUS,
620 src.containerLiveRegionStatus().utf8());
621 dst->AddStringAttribute(
622 ui::AX_ATTR_CONTAINER_LIVE_RELEVANT,
623 src.containerLiveRegionRelevant().utf8());
624 }
625
626 if (dst->role == ui::AX_ROLE_PROGRESS_INDICATOR ||
627 dst->role == ui::AX_ROLE_METER ||
628 dst->role == ui::AX_ROLE_SCROLL_BAR ||
629 dst->role == ui::AX_ROLE_SLIDER ||
630 dst->role == ui::AX_ROLE_SPIN_BUTTON) {
631 dst->AddFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, src.valueForRange());
632 dst->AddFloatAttribute(ui::AX_ATTR_MAX_VALUE_FOR_RANGE,
633 src.maxValueForRange());
634 dst->AddFloatAttribute(ui::AX_ATTR_MIN_VALUE_FOR_RANGE,
635 src.minValueForRange());
636 }
637
638 if (dst->role == ui::AX_ROLE_ROOT_WEB_AREA)
639 dst->AddStringAttribute(ui::AX_ATTR_HTML_TAG, "#document");
640
641 if (dst->role == ui::AX_ROLE_TABLE) {
642 int column_count = src.columnCount();
643 int row_count = src.rowCount();
644 if (column_count > 0 && row_count > 0) {
645 std::set<int32_t> unique_cell_id_set;
646 std::vector<int32_t> cell_ids;
647 std::vector<int32_t> unique_cell_ids;
648 dst->AddIntAttribute(ui::AX_ATTR_TABLE_COLUMN_COUNT, column_count);
649 dst->AddIntAttribute(ui::AX_ATTR_TABLE_ROW_COUNT, row_count);
650 WebAXObject header = src.headerContainerObject();
651 if (!header.isDetached())
652 dst->AddIntAttribute(ui::AX_ATTR_TABLE_HEADER_ID, header.axID());
653 for (int i = 0; i < column_count * row_count; ++i) {
654 WebAXObject cell = src.cellForColumnAndRow(
655 i % column_count, i / column_count);
656 int cell_id = -1;
657 if (!cell.isDetached()) {
658 cell_id = cell.axID();
659 if (unique_cell_id_set.find(cell_id) == unique_cell_id_set.end()) {
660 unique_cell_id_set.insert(cell_id);
661 unique_cell_ids.push_back(cell_id);
662 }
663 }
664 cell_ids.push_back(cell_id);
665 }
666 dst->AddIntListAttribute(ui::AX_ATTR_CELL_IDS, cell_ids);
667 dst->AddIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS, unique_cell_ids);
668 }
669 }
670
671 if (dst->role == ui::AX_ROLE_ROW) {
672 dst->AddIntAttribute(ui::AX_ATTR_TABLE_ROW_INDEX, src.rowIndex());
673 WebAXObject header = src.rowHeader();
674 if (!header.isDetached())
675 dst->AddIntAttribute(ui::AX_ATTR_TABLE_ROW_HEADER_ID, header.axID());
676 }
677
678 if (dst->role == ui::AX_ROLE_COLUMN) {
679 dst->AddIntAttribute(ui::AX_ATTR_TABLE_COLUMN_INDEX, src.columnIndex());
680 WebAXObject header = src.columnHeader();
681 if (!header.isDetached())
682 dst->AddIntAttribute(ui::AX_ATTR_TABLE_COLUMN_HEADER_ID, header.axID());
683 }
684
685 if (dst->role == ui::AX_ROLE_CELL ||
686 dst->role == ui::AX_ROLE_ROW_HEADER ||
687 dst->role == ui::AX_ROLE_COLUMN_HEADER) {
688 dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_INDEX,
689 src.cellColumnIndex());
690 dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN,
691 src.cellColumnSpan());
692 dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_INDEX, src.cellRowIndex());
693 dst->AddIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_SPAN, src.cellRowSpan());
694 }
695
696 if ((dst->role == ui::AX_ROLE_ROW_HEADER ||
697 dst->role == ui::AX_ROLE_COLUMN_HEADER) && src.sortDirection()) {
698 dst->AddIntAttribute(ui::AX_ATTR_SORT_DIRECTION,
699 AXSortDirectionFromBlink(src.sortDirection()));
700 }
701
702 // Add the ids of *indirect* children - those who are children of this node, 717 // Add the ids of *indirect* children - those who are children of this node,
703 // but whose parent is *not* this node. One example is a table 718 // but whose parent is *not* this node. One example is a table
704 // cell, which is a child of both a row and a column. Because the cell's 719 // cell, which is a child of both a row and a column. Because the cell's
705 // parent is the row, the row adds it as a child, and the column adds it 720 // parent is the row, the row adds it as a child, and the column adds it
706 // as an indirect child. 721 // as an indirect child.
707 int child_count = src.childCount(); 722 int child_count = src.childCount();
708 for (int i = 0; i < child_count; ++i) { 723 for (int i = 0; i < child_count; ++i) {
709 WebAXObject child = src.childAt(i); 724 WebAXObject child = src.childAt(i);
710 std::vector<int32_t> indirect_child_ids; 725 std::vector<int32_t> indirect_child_ids;
711 if (!is_iframe && !child.isDetached() && !IsParentUnignoredOf(src, child)) 726 if (!is_iframe && !child.isDetached() && !IsParentUnignoredOf(src, child))
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 return WebAXObject(); 772 return WebAXObject();
758 773
759 WebDocument document = render_frame_->GetWebFrame()->document(); 774 WebDocument document = render_frame_->GetWebFrame()->document();
760 if (!document.isNull()) 775 if (!document.isNull())
761 return document.accessibilityObject(); 776 return document.accessibilityObject();
762 777
763 return WebAXObject(); 778 return WebAXObject();
764 } 779 }
765 780
766 } // namespace content 781 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/accessibility/blink_ax_tree_source.h ('k') | content/renderer/accessibility/render_accessibility_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698