OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 return StaticTextRole; | 240 return StaticTextRole; |
241 if (cssBox && isImageOrAltText(cssBox, node)) { | 241 if (cssBox && isImageOrAltText(cssBox, node)) { |
242 if (node && node->isLink()) | 242 if (node && node->isLink()) |
243 return ImageMapRole; | 243 return ImageMapRole; |
244 if (isHTMLInputElement(node)) | 244 if (isHTMLInputElement(node)) |
245 return ariaHasPopup() ? PopUpButtonRole : ButtonRole; | 245 return ariaHasPopup() ? PopUpButtonRole : ButtonRole; |
246 if (isSVGImage()) | 246 if (isSVGImage()) |
247 return SVGRootRole; | 247 return SVGRootRole; |
248 return ImageRole; | 248 return ImageRole; |
249 } | 249 } |
250 // Note: if JavaScript is disabled, the layoutObject won't be a LayoutHTMLCanv
as. | 250 // Note: if JavaScript is disabled, the layoutObject won't be a |
| 251 // LayoutHTMLCanvas. |
251 if (isHTMLCanvasElement(node) && m_layoutObject->isCanvas()) | 252 if (isHTMLCanvasElement(node) && m_layoutObject->isCanvas()) |
252 return CanvasRole; | 253 return CanvasRole; |
253 | 254 |
254 if (cssBox && cssBox->isLayoutView()) | 255 if (cssBox && cssBox->isLayoutView()) |
255 return WebAreaRole; | 256 return WebAreaRole; |
256 | 257 |
257 if (m_layoutObject->isSVGImage()) | 258 if (m_layoutObject->isSVGImage()) |
258 return ImageRole; | 259 return ImageRole; |
259 if (m_layoutObject->isSVGRoot()) | 260 if (m_layoutObject->isSVGRoot()) |
260 return SVGRootRole; | 261 return SVGRootRole; |
(...skipping 15 matching lines...) Expand all Loading... |
276 if ((m_ariaRole = determineAriaRoleAttribute()) != UnknownRole) | 277 if ((m_ariaRole = determineAriaRoleAttribute()) != UnknownRole) |
277 return m_ariaRole; | 278 return m_ariaRole; |
278 | 279 |
279 AccessibilityRole role = nativeAccessibilityRoleIgnoringAria(); | 280 AccessibilityRole role = nativeAccessibilityRoleIgnoringAria(); |
280 if (role != UnknownRole) | 281 if (role != UnknownRole) |
281 return role; | 282 return role; |
282 | 283 |
283 if (m_layoutObject->isLayoutBlockFlow()) | 284 if (m_layoutObject->isLayoutBlockFlow()) |
284 return GroupRole; | 285 return GroupRole; |
285 | 286 |
286 // If the element does not have role, but it has ARIA attributes, accessibilit
y should fallback to exposing it as a group. | 287 // If the element does not have role, but it has ARIA attributes, |
| 288 // accessibility should fallback to exposing it as a group. |
287 if (supportsARIAAttributes()) | 289 if (supportsARIAAttributes()) |
288 return GroupRole; | 290 return GroupRole; |
289 | 291 |
290 return UnknownRole; | 292 return UnknownRole; |
291 } | 293 } |
292 | 294 |
293 void AXLayoutObject::init() { | 295 void AXLayoutObject::init() { |
294 AXNodeObject::init(); | 296 AXNodeObject::init(); |
295 } | 297 } |
296 | 298 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 if (body && hasEditableStyle(*body)) | 397 if (body && hasEditableStyle(*body)) |
396 return false; | 398 return false; |
397 | 399 |
398 return !hasEditableStyle(document); | 400 return !hasEditableStyle(document); |
399 } | 401 } |
400 | 402 |
401 return AXNodeObject::isReadOnly(); | 403 return AXNodeObject::isReadOnly(); |
402 } | 404 } |
403 | 405 |
404 bool AXLayoutObject::isVisited() const { | 406 bool AXLayoutObject::isVisited() const { |
405 // FIXME: Is it a privacy violation to expose visited information to accessibi
lity APIs? | 407 // FIXME: Is it a privacy violation to expose visited information to |
| 408 // accessibility APIs? |
406 return m_layoutObject->style()->isLink() && | 409 return m_layoutObject->style()->isLink() && |
407 m_layoutObject->style()->insideLink() == InsideVisitedLink; | 410 m_layoutObject->style()->insideLink() == InsideVisitedLink; |
408 } | 411 } |
409 | 412 |
410 // | 413 // |
411 // Check object state. | 414 // Check object state. |
412 // | 415 // |
413 | 416 |
414 bool AXLayoutObject::isFocused() const { | 417 bool AXLayoutObject::isFocused() const { |
415 if (!getDocument()) | 418 if (!getDocument()) |
416 return false; | 419 return false; |
417 | 420 |
418 Element* focusedElement = getDocument()->focusedElement(); | 421 Element* focusedElement = getDocument()->focusedElement(); |
419 if (!focusedElement) | 422 if (!focusedElement) |
420 return false; | 423 return false; |
421 AXObject* focusedObject = axObjectCache().getOrCreate(focusedElement); | 424 AXObject* focusedObject = axObjectCache().getOrCreate(focusedElement); |
422 if (!focusedObject || !focusedObject->isAXLayoutObject()) | 425 if (!focusedObject || !focusedObject->isAXLayoutObject()) |
423 return false; | 426 return false; |
424 | 427 |
425 // A web area is represented by the Document node in the DOM tree, which isn't
focusable. | 428 // A web area is represented by the Document node in the DOM tree, which isn't |
426 // Check instead if the frame's selection controller is focused | 429 // focusable. Check instead if the frame's selection controller is focused |
427 if (focusedObject == this || | 430 if (focusedObject == this || |
428 (roleValue() == WebAreaRole && | 431 (roleValue() == WebAreaRole && |
429 getDocument()->frame()->selection().isFocusedAndActive())) | 432 getDocument()->frame()->selection().isFocusedAndActive())) |
430 return true; | 433 return true; |
431 | 434 |
432 return false; | 435 return false; |
433 } | 436 } |
434 | 437 |
435 bool AXLayoutObject::isSelected() const { | 438 bool AXLayoutObject::isSelected() const { |
436 if (!getLayoutObject() || !getNode()) | 439 if (!getLayoutObject() || !getNode()) |
(...skipping 14 matching lines...) Expand all Loading... |
451 | 454 |
452 return false; | 455 return false; |
453 } | 456 } |
454 | 457 |
455 // | 458 // |
456 // Whether objects are ignored, i.e. not included in the tree. | 459 // Whether objects are ignored, i.e. not included in the tree. |
457 // | 460 // |
458 | 461 |
459 AXObjectInclusion AXLayoutObject::defaultObjectInclusion( | 462 AXObjectInclusion AXLayoutObject::defaultObjectInclusion( |
460 IgnoredReasons* ignoredReasons) const { | 463 IgnoredReasons* ignoredReasons) const { |
461 // The following cases can apply to any element that's a subclass of AXLayoutO
bject. | 464 // The following cases can apply to any element that's a subclass of |
| 465 // AXLayoutObject. |
462 | 466 |
463 if (!m_layoutObject) { | 467 if (!m_layoutObject) { |
464 if (ignoredReasons) | 468 if (ignoredReasons) |
465 ignoredReasons->append(IgnoredReason(AXNotRendered)); | 469 ignoredReasons->append(IgnoredReason(AXNotRendered)); |
466 return IgnoreObject; | 470 return IgnoreObject; |
467 } | 471 } |
468 | 472 |
469 if (m_layoutObject->style()->visibility() != EVisibility::Visible) { | 473 if (m_layoutObject->style()->visibility() != EVisibility::Visible) { |
470 // aria-hidden is meant to override visibility as the determinant in AX hier
archy inclusion. | 474 // aria-hidden is meant to override visibility as the determinant in AX |
| 475 // hierarchy inclusion. |
471 if (equalIgnoringCase(getAttribute(aria_hiddenAttr), "false")) | 476 if (equalIgnoringCase(getAttribute(aria_hiddenAttr), "false")) |
472 return DefaultBehavior; | 477 return DefaultBehavior; |
473 | 478 |
474 if (ignoredReasons) | 479 if (ignoredReasons) |
475 ignoredReasons->append(IgnoredReason(AXNotVisible)); | 480 ignoredReasons->append(IgnoredReason(AXNotVisible)); |
476 return IgnoreObject; | 481 return IgnoreObject; |
477 } | 482 } |
478 | 483 |
479 return AXObject::defaultObjectInclusion(ignoredReasons); | 484 return AXObject::defaultObjectInclusion(ignoredReasons); |
480 } | 485 } |
481 | 486 |
482 bool AXLayoutObject::computeAccessibilityIsIgnored( | 487 bool AXLayoutObject::computeAccessibilityIsIgnored( |
483 IgnoredReasons* ignoredReasons) const { | 488 IgnoredReasons* ignoredReasons) const { |
484 #if ENABLE(ASSERT) | 489 #if ENABLE(ASSERT) |
485 ASSERT(m_initialized); | 490 ASSERT(m_initialized); |
486 #endif | 491 #endif |
487 | 492 |
488 if (!m_layoutObject) | 493 if (!m_layoutObject) |
489 return true; | 494 return true; |
490 | 495 |
491 // Check first if any of the common reasons cause this element to be ignored. | 496 // Check first if any of the common reasons cause this element to be ignored. |
492 // Then process other use cases that need to be applied to all the various rol
es | 497 // Then process other use cases that need to be applied to all the various |
493 // that AXLayoutObjects take on. | 498 // roles that AXLayoutObjects take on. |
494 AXObjectInclusion decision = defaultObjectInclusion(ignoredReasons); | 499 AXObjectInclusion decision = defaultObjectInclusion(ignoredReasons); |
495 if (decision == IncludeObject) | 500 if (decision == IncludeObject) |
496 return false; | 501 return false; |
497 if (decision == IgnoreObject) | 502 if (decision == IgnoreObject) |
498 return true; | 503 return true; |
499 | 504 |
500 // If this element is within a parent that cannot have children, it should not
be exposed | 505 // If this element is within a parent that cannot have children, it should not |
| 506 // be exposed. |
501 if (isDescendantOfLeafNode()) { | 507 if (isDescendantOfLeafNode()) { |
502 if (ignoredReasons) | 508 if (ignoredReasons) |
503 ignoredReasons->append( | 509 ignoredReasons->append( |
504 IgnoredReason(AXAncestorIsLeafNode, leafNodeAncestor())); | 510 IgnoredReason(AXAncestorIsLeafNode, leafNodeAncestor())); |
505 return true; | 511 return true; |
506 } | 512 } |
507 | 513 |
508 if (roleValue() == IgnoredRole) { | 514 if (roleValue() == IgnoredRole) { |
509 if (ignoredReasons) | 515 if (ignoredReasons) |
510 ignoredReasons->append(IgnoredReason(AXUninteresting)); | 516 ignoredReasons->append(IgnoredReason(AXUninteresting)); |
(...skipping 13 matching lines...) Expand all Loading... |
524 } | 530 } |
525 | 531 |
526 // An ARIA tree can only have tree items and static text as children. | 532 // An ARIA tree can only have tree items and static text as children. |
527 if (AXObject* treeAncestor = treeAncestorDisallowingChild()) { | 533 if (AXObject* treeAncestor = treeAncestorDisallowingChild()) { |
528 if (ignoredReasons) | 534 if (ignoredReasons) |
529 ignoredReasons->append( | 535 ignoredReasons->append( |
530 IgnoredReason(AXAncestorDisallowsChild, treeAncestor)); | 536 IgnoredReason(AXAncestorDisallowsChild, treeAncestor)); |
531 return true; | 537 return true; |
532 } | 538 } |
533 | 539 |
534 // A LayoutPart is an iframe element or embedded object element or something l
ike | 540 // A LayoutPart is an iframe element or embedded object element or something |
535 // that. We don't want to ignore those. | 541 // like that. We don't want to ignore those. |
536 if (m_layoutObject->isLayoutPart()) | 542 if (m_layoutObject->isLayoutPart()) |
537 return false; | 543 return false; |
538 | 544 |
539 // Make sure renderers with layers stay in the tree. | 545 // Make sure renderers with layers stay in the tree. |
540 if (getLayoutObject() && getLayoutObject()->hasLayer() && getNode() && | 546 if (getLayoutObject() && getLayoutObject()->hasLayer() && getNode() && |
541 getNode()->hasChildren()) | 547 getNode()->hasChildren()) |
542 return false; | 548 return false; |
543 | 549 |
544 // find out if this element is inside of a label element. | 550 // Find out if this element is inside of a label element. If so, it may be |
545 // if so, it may be ignored because it's the label for a checkbox or radio but
ton | 551 // ignored because it's the label for a checkbox or radio button. |
546 AXObject* controlObject = correspondingControlForLabelElement(); | 552 AXObject* controlObject = correspondingControlForLabelElement(); |
547 if (controlObject && controlObject->isCheckboxOrRadio() && | 553 if (controlObject && controlObject->isCheckboxOrRadio() && |
548 controlObject->nameFromLabelElement()) { | 554 controlObject->nameFromLabelElement()) { |
549 if (ignoredReasons) { | 555 if (ignoredReasons) { |
550 HTMLLabelElement* label = labelElementContainer(); | 556 HTMLLabelElement* label = labelElementContainer(); |
551 if (label && label != getNode()) { | 557 if (label && label != getNode()) { |
552 AXObject* labelAXObject = axObjectCache().getOrCreate(label); | 558 AXObject* labelAXObject = axObjectCache().getOrCreate(label); |
553 ignoredReasons->append(IgnoredReason(AXLabelContainer, labelAXObject)); | 559 ignoredReasons->append(IgnoredReason(AXLabelContainer, labelAXObject)); |
554 } | 560 } |
555 | 561 |
556 ignoredReasons->append(IgnoredReason(AXLabelFor, controlObject)); | 562 ignoredReasons->append(IgnoredReason(AXLabelFor, controlObject)); |
557 } | 563 } |
558 return true; | 564 return true; |
559 } | 565 } |
560 | 566 |
561 if (m_layoutObject->isBR()) | 567 if (m_layoutObject->isBR()) |
562 return false; | 568 return false; |
563 | 569 |
564 if (m_layoutObject->isText()) { | 570 if (m_layoutObject->isText()) { |
565 // static text beneath MenuItems and MenuButtons are just reported along wit
h the menu item, so it's ignored on an individual level | 571 // Static text beneath MenuItems and MenuButtons are just reported along |
| 572 // with the menu item, so it's ignored on an individual level. |
566 AXObject* parent = parentObjectUnignored(); | 573 AXObject* parent = parentObjectUnignored(); |
567 if (parent && (parent->ariaRoleAttribute() == MenuItemRole || | 574 if (parent && (parent->ariaRoleAttribute() == MenuItemRole || |
568 parent->ariaRoleAttribute() == MenuButtonRole)) { | 575 parent->ariaRoleAttribute() == MenuButtonRole)) { |
569 if (ignoredReasons) | 576 if (ignoredReasons) |
570 ignoredReasons->append( | 577 ignoredReasons->append( |
571 IgnoredReason(AXStaticTextUsedAsNameFor, parent)); | 578 IgnoredReason(AXStaticTextUsedAsNameFor, parent)); |
572 return true; | 579 return true; |
573 } | 580 } |
574 LayoutText* layoutText = toLayoutText(m_layoutObject); | 581 LayoutText* layoutText = toLayoutText(m_layoutObject); |
575 if (!layoutText->hasTextBoxes()) { | 582 if (!layoutText->hasTextBoxes()) { |
576 if (ignoredReasons) | 583 if (ignoredReasons) |
577 ignoredReasons->append(IgnoredReason(AXEmptyText)); | 584 ignoredReasons->append(IgnoredReason(AXEmptyText)); |
578 return true; | 585 return true; |
579 } | 586 } |
580 | 587 |
581 // Don't ignore static text in editable text controls. | 588 // Don't ignore static text in editable text controls. |
582 for (AXObject* parent = parentObject(); parent; | 589 for (AXObject* parent = parentObject(); parent; |
583 parent = parent->parentObject()) { | 590 parent = parent->parentObject()) { |
584 if (parent->roleValue() == TextFieldRole) | 591 if (parent->roleValue() == TextFieldRole) |
585 return false; | 592 return false; |
586 } | 593 } |
587 | 594 |
588 // text elements that are just empty whitespace should not be returned | 595 // Text elements that are just empty whitespace should not be returned. |
589 // FIXME(dmazzoni): we probably shouldn't ignore this if the style is 'pre',
or similar... | 596 // FIXME(dmazzoni): we probably shouldn't ignore this if the style is 'pre', |
| 597 // or similar... |
590 if (layoutText->text().impl()->containsOnlyWhitespace()) { | 598 if (layoutText->text().impl()->containsOnlyWhitespace()) { |
591 if (ignoredReasons) | 599 if (ignoredReasons) |
592 ignoredReasons->append(IgnoredReason(AXEmptyText)); | 600 ignoredReasons->append(IgnoredReason(AXEmptyText)); |
593 return true; | 601 return true; |
594 } | 602 } |
595 return false; | 603 return false; |
596 } | 604 } |
597 | 605 |
598 if (isHeading()) | 606 if (isHeading()) |
599 return false; | 607 return false; |
600 | 608 |
601 if (isLandmarkRelated()) | 609 if (isLandmarkRelated()) |
602 return false; | 610 return false; |
603 | 611 |
604 // Header and footer tags may also be exposed as landmark roles but not always
. | 612 // Header and footer tags may also be exposed as landmark roles but not |
| 613 // always. |
605 if (getNode() && | 614 if (getNode() && |
606 (getNode()->hasTagName(headerTag) || getNode()->hasTagName(footerTag))) | 615 (getNode()->hasTagName(headerTag) || getNode()->hasTagName(footerTag))) |
607 return false; | 616 return false; |
608 | 617 |
609 if (isLink()) | 618 if (isLink()) |
610 return false; | 619 return false; |
611 | 620 |
612 // all controls are accessible | 621 // all controls are accessible |
613 if (isControl()) | 622 if (isControl()) |
614 return false; | 623 return false; |
615 | 624 |
616 if (ariaRoleAttribute() != UnknownRole) | 625 if (ariaRoleAttribute() != UnknownRole) |
617 return false; | 626 return false; |
618 | 627 |
619 // don't ignore labels, because they serve as TitleUIElements | 628 // don't ignore labels, because they serve as TitleUIElements |
620 Node* node = m_layoutObject->node(); | 629 Node* node = m_layoutObject->node(); |
621 if (isHTMLLabelElement(node)) | 630 if (isHTMLLabelElement(node)) |
622 return false; | 631 return false; |
623 | 632 |
624 // Anything that is content editable should not be ignored. | 633 // Anything that is content editable should not be ignored. |
625 // However, one cannot just call node->hasEditableStyle() since that will ask
if its parents | 634 // However, one cannot just call node->hasEditableStyle() since that will ask |
626 // are also editable. Only the top level content editable region should be exp
osed. | 635 // if its parents are also editable. Only the top level content editable |
| 636 // region should be exposed. |
627 if (hasContentEditableAttributeSet()) | 637 if (hasContentEditableAttributeSet()) |
628 return false; | 638 return false; |
629 | 639 |
630 if (roleValue() == AbbrRole) | 640 if (roleValue() == AbbrRole) |
631 return false; | 641 return false; |
632 | 642 |
633 // List items play an important role in defining the structure of lists. They
should not be ignored. | 643 // List items play an important role in defining the structure of lists. They |
| 644 // should not be ignored. |
634 if (roleValue() == ListItemRole) | 645 if (roleValue() == ListItemRole) |
635 return false; | 646 return false; |
636 | 647 |
637 if (roleValue() == BlockquoteRole) | 648 if (roleValue() == BlockquoteRole) |
638 return false; | 649 return false; |
639 | 650 |
640 if (roleValue() == DialogRole) | 651 if (roleValue() == DialogRole) |
641 return false; | 652 return false; |
642 | 653 |
643 if (roleValue() == FigcaptionRole) | 654 if (roleValue() == FigcaptionRole) |
(...skipping 20 matching lines...) Expand all Loading... |
664 if (roleValue() == SplitterRole) | 675 if (roleValue() == SplitterRole) |
665 return false; | 676 return false; |
666 | 677 |
667 if (roleValue() == TimeRole) | 678 if (roleValue() == TimeRole) |
668 return false; | 679 return false; |
669 | 680 |
670 // if this element has aria attributes on it, it should not be ignored. | 681 // if this element has aria attributes on it, it should not be ignored. |
671 if (supportsARIAAttributes()) | 682 if (supportsARIAAttributes()) |
672 return false; | 683 return false; |
673 | 684 |
674 // <span> tags are inline tags and not meant to convey information if they hav
e no other aria | 685 // <span> tags are inline tags and not meant to convey information if they |
675 // information on them. If we don't ignore them, they may emit signals expecte
d to come from | 686 // have no other aria information on them. If we don't ignore them, they may |
676 // their parent. In addition, because included spans are GroupRole objects, an
d GroupRole | 687 // emit signals expected to come from their parent. In addition, because |
677 // objects are often containers with meaningful information, the inclusion of
a span can have | 688 // included spans are GroupRole objects, and GroupRole objects are often |
678 // the side effect of causing the immediate parent accessible to be ignored. T
his is especially | 689 // containers with meaningful information, the inclusion of a span can have |
679 // problematic for platforms which have distinct roles for textual block eleme
nts. | 690 // the side effect of causing the immediate parent accessible to be ignored. |
| 691 // This is especially problematic for platforms which have distinct roles for |
| 692 // textual block elements. |
680 if (isHTMLSpanElement(node)) { | 693 if (isHTMLSpanElement(node)) { |
681 if (ignoredReasons) | 694 if (ignoredReasons) |
682 ignoredReasons->append(IgnoredReason(AXUninteresting)); | 695 ignoredReasons->append(IgnoredReason(AXUninteresting)); |
683 return true; | 696 return true; |
684 } | 697 } |
685 | 698 |
686 // ignore images seemingly used as spacers | 699 // ignore images seemingly used as spacers |
687 if (isImage()) { | 700 if (isImage()) { |
688 // If the image can take focus, it should not be ignored, lest the user not
be able to interact with something important. | 701 // If the image can take focus, it should not be ignored, lest the user not |
| 702 // be able to interact with something important. |
689 if (canSetFocusAttribute()) | 703 if (canSetFocusAttribute()) |
690 return false; | 704 return false; |
691 | 705 |
692 if (node && node->isElementNode()) { | 706 if (node && node->isElementNode()) { |
693 Element* elt = toElement(node); | 707 Element* elt = toElement(node); |
694 const AtomicString& alt = elt->getAttribute(altAttr); | 708 const AtomicString& alt = elt->getAttribute(altAttr); |
695 // don't ignore an image that has an alt tag | 709 // don't ignore an image that has an alt tag |
696 if (!alt.getString().containsOnlyWhitespace()) | 710 if (!alt.getString().containsOnlyWhitespace()) |
697 return false; | 711 return false; |
698 // informal standard is to ignore images with zero-length alt strings | 712 // informal standard is to ignore images with zero-length alt strings |
699 if (!alt.isNull()) { | 713 if (!alt.isNull()) { |
700 if (ignoredReasons) | 714 if (ignoredReasons) |
701 ignoredReasons->append(IgnoredReason(AXEmptyAlt)); | 715 ignoredReasons->append(IgnoredReason(AXEmptyAlt)); |
702 return true; | 716 return true; |
703 } | 717 } |
704 } | 718 } |
705 | 719 |
706 if (isNativeImage() && m_layoutObject->isImage()) { | 720 if (isNativeImage() && m_layoutObject->isImage()) { |
707 // check for one-dimensional image | 721 // check for one-dimensional image |
708 LayoutImage* image = toLayoutImage(m_layoutObject); | 722 LayoutImage* image = toLayoutImage(m_layoutObject); |
709 if (image->size().height() <= 1 || image->size().width() <= 1) { | 723 if (image->size().height() <= 1 || image->size().width() <= 1) { |
710 if (ignoredReasons) | 724 if (ignoredReasons) |
711 ignoredReasons->append(IgnoredReason(AXProbablyPresentational)); | 725 ignoredReasons->append(IgnoredReason(AXProbablyPresentational)); |
712 return true; | 726 return true; |
713 } | 727 } |
714 | 728 |
715 // check whether laid out image was stretched from one-dimensional file im
age | 729 // Check whether laid out image was stretched from one-dimensional file |
| 730 // image. |
716 if (image->cachedImage()) { | 731 if (image->cachedImage()) { |
717 LayoutSize imageSize = image->cachedImage()->imageSize( | 732 LayoutSize imageSize = image->cachedImage()->imageSize( |
718 LayoutObject::shouldRespectImageOrientation(m_layoutObject), | 733 LayoutObject::shouldRespectImageOrientation(m_layoutObject), |
719 image->view()->zoomFactor()); | 734 image->view()->zoomFactor()); |
720 if (imageSize.height() <= 1 || imageSize.width() <= 1) { | 735 if (imageSize.height() <= 1 || imageSize.width() <= 1) { |
721 if (ignoredReasons) | 736 if (ignoredReasons) |
722 ignoredReasons->append(IgnoredReason(AXProbablyPresentational)); | 737 ignoredReasons->append(IgnoredReason(AXProbablyPresentational)); |
723 return true; | 738 return true; |
724 } | 739 } |
725 return false; | 740 return false; |
726 } | 741 } |
727 } | 742 } |
728 return false; | 743 return false; |
729 } | 744 } |
730 | 745 |
731 if (isCanvas()) { | 746 if (isCanvas()) { |
732 if (canvasHasFallbackContent()) | 747 if (canvasHasFallbackContent()) |
733 return false; | 748 return false; |
734 LayoutHTMLCanvas* canvas = toLayoutHTMLCanvas(m_layoutObject); | 749 LayoutHTMLCanvas* canvas = toLayoutHTMLCanvas(m_layoutObject); |
735 if (canvas->size().height() <= 1 || canvas->size().width() <= 1) { | 750 if (canvas->size().height() <= 1 || canvas->size().width() <= 1) { |
736 if (ignoredReasons) | 751 if (ignoredReasons) |
737 ignoredReasons->append(IgnoredReason(AXProbablyPresentational)); | 752 ignoredReasons->append(IgnoredReason(AXProbablyPresentational)); |
738 return true; | 753 return true; |
739 } | 754 } |
740 // Otherwise fall through; use presence of help text, title, or description
to decide. | 755 // Otherwise fall through; use presence of help text, title, or description |
| 756 // to decide. |
741 } | 757 } |
742 | 758 |
743 if (isWebArea() || m_layoutObject->isListMarker()) | 759 if (isWebArea() || m_layoutObject->isListMarker()) |
744 return false; | 760 return false; |
745 | 761 |
746 // Using the help text, title or accessibility description (so we | 762 // Using the help text, title or accessibility description (so we |
747 // check if there's some kind of accessible name for the element) | 763 // check if there's some kind of accessible name for the element) |
748 // to decide an element's visibility is not as definitive as | 764 // to decide an element's visibility is not as definitive as |
749 // previous checks, so this should remain as one of the last. | 765 // previous checks, so this should remain as one of the last. |
750 // | 766 // |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1024 AXObject* result = nullptr; | 1040 AXObject* result = nullptr; |
1025 for (InlineBox* next = inlineBox->nextOnLine(); next; | 1041 for (InlineBox* next = inlineBox->nextOnLine(); next; |
1026 next = next->nextOnLine()) { | 1042 next = next->nextOnLine()) { |
1027 LayoutObject* layoutObject = | 1043 LayoutObject* layoutObject = |
1028 LineLayoutAPIShim::layoutObjectFrom(next->getLineLayoutItem()); | 1044 LineLayoutAPIShim::layoutObjectFrom(next->getLineLayoutItem()); |
1029 result = axObjectCache().getOrCreate(layoutObject); | 1045 result = axObjectCache().getOrCreate(layoutObject); |
1030 if (result) | 1046 if (result) |
1031 break; | 1047 break; |
1032 } | 1048 } |
1033 | 1049 |
1034 // A static text node might span multiple lines. Try to return the first inlin
e | 1050 // A static text node might span multiple lines. Try to return the first |
1035 // text box within that static text if possible. | 1051 // inline text box within that static text if possible. |
1036 if (result && result->roleValue() == StaticTextRole && | 1052 if (result && result->roleValue() == StaticTextRole && |
1037 result->children().size()) | 1053 result->children().size()) |
1038 result = result->children()[0].get(); | 1054 result = result->children()[0].get(); |
1039 | 1055 |
1040 return result; | 1056 return result; |
1041 } | 1057 } |
1042 | 1058 |
1043 AXObject* AXLayoutObject::previousOnLine() const { | 1059 AXObject* AXLayoutObject::previousOnLine() const { |
1044 if (!getLayoutObject()) | 1060 if (!getLayoutObject()) |
1045 return nullptr; | 1061 return nullptr; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1077 // | 1093 // |
1078 | 1094 |
1079 String AXLayoutObject::stringValue() const { | 1095 String AXLayoutObject::stringValue() const { |
1080 if (!m_layoutObject) | 1096 if (!m_layoutObject) |
1081 return String(); | 1097 return String(); |
1082 | 1098 |
1083 LayoutBoxModelObject* cssBox = getLayoutBoxModelObject(); | 1099 LayoutBoxModelObject* cssBox = getLayoutBoxModelObject(); |
1084 | 1100 |
1085 if (cssBox && cssBox->isMenuList()) { | 1101 if (cssBox && cssBox->isMenuList()) { |
1086 // LayoutMenuList will go straight to the text() of its selected item. | 1102 // LayoutMenuList will go straight to the text() of its selected item. |
1087 // This has to be overridden in the case where the selected item has an ARIA
label. | 1103 // This has to be overridden in the case where the selected item has an ARIA |
| 1104 // label. |
1088 HTMLSelectElement* selectElement = | 1105 HTMLSelectElement* selectElement = |
1089 toHTMLSelectElement(m_layoutObject->node()); | 1106 toHTMLSelectElement(m_layoutObject->node()); |
1090 int selectedIndex = selectElement->selectedIndex(); | 1107 int selectedIndex = selectElement->selectedIndex(); |
1091 const HeapVector<Member<HTMLElement>>& listItems = | 1108 const HeapVector<Member<HTMLElement>>& listItems = |
1092 selectElement->listItems(); | 1109 selectElement->listItems(); |
1093 if (selectedIndex >= 0 && | 1110 if (selectedIndex >= 0 && |
1094 static_cast<size_t>(selectedIndex) < listItems.size()) { | 1111 static_cast<size_t>(selectedIndex) < listItems.size()) { |
1095 const AtomicString& overriddenDescription = | 1112 const AtomicString& overriddenDescription = |
1096 listItems[selectedIndex]->fastGetAttribute(aria_labelAttr); | 1113 listItems[selectedIndex]->fastGetAttribute(aria_labelAttr); |
1097 if (!overriddenDescription.isNull()) | 1114 if (!overriddenDescription.isNull()) |
1098 return overriddenDescription; | 1115 return overriddenDescription; |
1099 } | 1116 } |
1100 return toLayoutMenuList(m_layoutObject)->text(); | 1117 return toLayoutMenuList(m_layoutObject)->text(); |
1101 } | 1118 } |
1102 | 1119 |
1103 if (isWebArea()) { | 1120 if (isWebArea()) { |
1104 // FIXME: Why would a layoutObject exist when the Document isn't attached to
a frame? | 1121 // FIXME: Why would a layoutObject exist when the Document isn't attached to |
| 1122 // a frame? |
1105 if (m_layoutObject->frame()) | 1123 if (m_layoutObject->frame()) |
1106 return String(); | 1124 return String(); |
1107 | 1125 |
1108 ASSERT_NOT_REACHED(); | 1126 ASSERT_NOT_REACHED(); |
1109 } | 1127 } |
1110 | 1128 |
1111 if (isTextControl()) | 1129 if (isTextControl()) |
1112 return text(); | 1130 return text(); |
1113 | 1131 |
1114 if (m_layoutObject->isFileUploadControl()) | 1132 if (m_layoutObject->isFileUploadControl()) |
1115 return toLayoutFileUploadControl(m_layoutObject)->fileTextValue(); | 1133 return toLayoutFileUploadControl(m_layoutObject)->fileTextValue(); |
1116 | 1134 |
1117 // Handle other HTML input elements that aren't text controls, like date and t
ime | 1135 // Handle other HTML input elements that aren't text controls, like date and |
1118 // controls, by returning the string value, with the exception of checkboxes | 1136 // time controls, by returning the string value, with the exception of |
1119 // and radio buttons (which would return "on"). | 1137 // checkboxes and radio buttons (which would return "on"). |
1120 if (getNode() && isHTMLInputElement(getNode())) { | 1138 if (getNode() && isHTMLInputElement(getNode())) { |
1121 HTMLInputElement* input = toHTMLInputElement(getNode()); | 1139 HTMLInputElement* input = toHTMLInputElement(getNode()); |
1122 if (input->type() != InputTypeNames::checkbox && | 1140 if (input->type() != InputTypeNames::checkbox && |
1123 input->type() != InputTypeNames::radio) | 1141 input->type() != InputTypeNames::radio) |
1124 return input->value(); | 1142 return input->value(); |
1125 } | 1143 } |
1126 | 1144 |
1127 // FIXME: We might need to implement a value here for more types | 1145 // FIXME: We might need to implement a value here for more types |
1128 // FIXME: It would be better not to advertise a value at all for the types for
which we don't implement one; | 1146 // FIXME: It would be better not to advertise a value at all for the types for |
1129 // this would require subclassing or making accessibilityAttributeNames do som
ething other than return a | 1147 // which we don't implement one; this would require subclassing or making |
1130 // single static array. | 1148 // accessibilityAttributeNames do something other than return a single static |
| 1149 // array. |
1131 return String(); | 1150 return String(); |
1132 } | 1151 } |
1133 | 1152 |
1134 String AXLayoutObject::textAlternative(bool recursive, | 1153 String AXLayoutObject::textAlternative(bool recursive, |
1135 bool inAriaLabelledByTraversal, | 1154 bool inAriaLabelledByTraversal, |
1136 AXObjectSet& visited, | 1155 AXObjectSet& visited, |
1137 AXNameFrom& nameFrom, | 1156 AXNameFrom& nameFrom, |
1138 AXRelatedObjectVector* relatedObjects, | 1157 AXRelatedObjectVector* relatedObjects, |
1139 NameSources* nameSources) const { | 1158 NameSources* nameSources) const { |
1140 if (m_layoutObject) { | 1159 if (m_layoutObject) { |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1296 const AtomicString& relevant = getAttribute(aria_relevantAttr); | 1315 const AtomicString& relevant = getAttribute(aria_relevantAttr); |
1297 | 1316 |
1298 // Default aria-relevant = "additions text". | 1317 // Default aria-relevant = "additions text". |
1299 if (relevant.isEmpty()) | 1318 if (relevant.isEmpty()) |
1300 return defaultLiveRegionRelevant; | 1319 return defaultLiveRegionRelevant; |
1301 | 1320 |
1302 return relevant; | 1321 return relevant; |
1303 } | 1322 } |
1304 | 1323 |
1305 bool AXLayoutObject::liveRegionAtomic() const { | 1324 bool AXLayoutObject::liveRegionAtomic() const { |
1306 // ARIA roles "alert" and "status" should have an implicit aria-atomic value o
f true. | 1325 // ARIA roles "alert" and "status" should have an implicit aria-atomic value |
| 1326 // of true. |
1307 if (getAttribute(aria_atomicAttr).isEmpty() && | 1327 if (getAttribute(aria_atomicAttr).isEmpty() && |
1308 (roleValue() == AlertRole || roleValue() == StatusRole)) { | 1328 (roleValue() == AlertRole || roleValue() == StatusRole)) { |
1309 return true; | 1329 return true; |
1310 } | 1330 } |
1311 return elementAttributeValue(aria_atomicAttr); | 1331 return elementAttributeValue(aria_atomicAttr); |
1312 } | 1332 } |
1313 | 1333 |
1314 bool AXLayoutObject::liveRegionBusy() const { | 1334 bool AXLayoutObject::liveRegionBusy() const { |
1315 return elementAttributeValue(aria_busyAttr); | 1335 return elementAttributeValue(aria_busyAttr); |
1316 } | 1336 } |
(...skipping 25 matching lines...) Expand all Loading... |
1342 return nullptr; | 1362 return nullptr; |
1343 } | 1363 } |
1344 | 1364 |
1345 LayoutObject* obj = node->layoutObject(); | 1365 LayoutObject* obj = node->layoutObject(); |
1346 if (!obj) | 1366 if (!obj) |
1347 return nullptr; | 1367 return nullptr; |
1348 | 1368 |
1349 AXObject* result = axObjectCache().getOrCreate(obj); | 1369 AXObject* result = axObjectCache().getOrCreate(obj); |
1350 result->updateChildrenIfNecessary(); | 1370 result->updateChildrenIfNecessary(); |
1351 | 1371 |
1352 // Allow the element to perform any hit-testing it might need to do to reach n
on-layout children. | 1372 // Allow the element to perform any hit-testing it might need to do to reach |
| 1373 // non-layout children. |
1353 result = result->elementAccessibilityHitTest(point); | 1374 result = result->elementAccessibilityHitTest(point); |
1354 if (result && result->accessibilityIsIgnored()) { | 1375 if (result && result->accessibilityIsIgnored()) { |
1355 // If this element is the label of a control, a hit test should return the c
ontrol. | 1376 // If this element is the label of a control, a hit test should return the |
| 1377 // control. |
1356 if (result->isAXLayoutObject()) { | 1378 if (result->isAXLayoutObject()) { |
1357 AXObject* controlObject = | 1379 AXObject* controlObject = |
1358 toAXLayoutObject(result)->correspondingControlForLabelElement(); | 1380 toAXLayoutObject(result)->correspondingControlForLabelElement(); |
1359 if (controlObject && controlObject->nameFromLabelElement()) | 1381 if (controlObject && controlObject->nameFromLabelElement()) |
1360 return controlObject; | 1382 return controlObject; |
1361 } | 1383 } |
1362 | 1384 |
1363 result = result->parentObjectUnignored(); | 1385 result = result->parentObjectUnignored(); |
1364 } | 1386 } |
1365 | 1387 |
(...skipping 13 matching lines...) Expand all Loading... |
1379 // | 1401 // |
1380 | 1402 |
1381 AXObject* AXLayoutObject::computeParent() const { | 1403 AXObject* AXLayoutObject::computeParent() const { |
1382 ASSERT(!isDetached()); | 1404 ASSERT(!isDetached()); |
1383 if (!m_layoutObject) | 1405 if (!m_layoutObject) |
1384 return 0; | 1406 return 0; |
1385 | 1407 |
1386 if (ariaRoleAttribute() == MenuBarRole) | 1408 if (ariaRoleAttribute() == MenuBarRole) |
1387 return axObjectCache().getOrCreate(m_layoutObject->parent()); | 1409 return axObjectCache().getOrCreate(m_layoutObject->parent()); |
1388 | 1410 |
1389 // menuButton and its corresponding menu are DOM siblings, but Accessibility n
eeds them to be parent/child | 1411 // menuButton and its corresponding menu are DOM siblings, but Accessibility |
| 1412 // needs them to be parent/child. |
1390 if (ariaRoleAttribute() == MenuRole) { | 1413 if (ariaRoleAttribute() == MenuRole) { |
1391 AXObject* parent = menuButtonForMenu(); | 1414 AXObject* parent = menuButtonForMenu(); |
1392 if (parent) | 1415 if (parent) |
1393 return parent; | 1416 return parent; |
1394 } | 1417 } |
1395 | 1418 |
1396 LayoutObject* parentObj = layoutParentObject(); | 1419 LayoutObject* parentObj = layoutParentObject(); |
1397 if (parentObj) | 1420 if (parentObj) |
1398 return axObjectCache().getOrCreate(parentObj); | 1421 return axObjectCache().getOrCreate(parentObj); |
1399 | 1422 |
1400 // A WebArea's parent should be the page popup owner, if any, otherwise null. | 1423 // A WebArea's parent should be the page popup owner, if any, otherwise null. |
1401 if (isWebArea()) { | 1424 if (isWebArea()) { |
1402 LocalFrame* frame = m_layoutObject->frame(); | 1425 LocalFrame* frame = m_layoutObject->frame(); |
1403 return axObjectCache().getOrCreate(frame->pagePopupOwner()); | 1426 return axObjectCache().getOrCreate(frame->pagePopupOwner()); |
1404 } | 1427 } |
1405 | 1428 |
1406 return 0; | 1429 return 0; |
1407 } | 1430 } |
1408 | 1431 |
1409 AXObject* AXLayoutObject::computeParentIfExists() const { | 1432 AXObject* AXLayoutObject::computeParentIfExists() const { |
1410 if (!m_layoutObject) | 1433 if (!m_layoutObject) |
1411 return 0; | 1434 return 0; |
1412 | 1435 |
1413 if (ariaRoleAttribute() == MenuBarRole) | 1436 if (ariaRoleAttribute() == MenuBarRole) |
1414 return axObjectCache().get(m_layoutObject->parent()); | 1437 return axObjectCache().get(m_layoutObject->parent()); |
1415 | 1438 |
1416 // menuButton and its corresponding menu are DOM siblings, but Accessibility n
eeds them to be parent/child | 1439 // menuButton and its corresponding menu are DOM siblings, but Accessibility |
| 1440 // needs them to be parent/child. |
1417 if (ariaRoleAttribute() == MenuRole) { | 1441 if (ariaRoleAttribute() == MenuRole) { |
1418 AXObject* parent = menuButtonForMenu(); | 1442 AXObject* parent = menuButtonForMenu(); |
1419 if (parent) | 1443 if (parent) |
1420 return parent; | 1444 return parent; |
1421 } | 1445 } |
1422 | 1446 |
1423 LayoutObject* parentObj = layoutParentObject(); | 1447 LayoutObject* parentObj = layoutParentObject(); |
1424 if (parentObj) | 1448 if (parentObj) |
1425 return axObjectCache().get(parentObj); | 1449 return axObjectCache().get(parentObj); |
1426 | 1450 |
1427 // A WebArea's parent should be the page popup owner, if any, otherwise null. | 1451 // A WebArea's parent should be the page popup owner, if any, otherwise null. |
1428 if (isWebArea()) { | 1452 if (isWebArea()) { |
1429 LocalFrame* frame = m_layoutObject->frame(); | 1453 LocalFrame* frame = m_layoutObject->frame(); |
1430 return axObjectCache().get(frame->pagePopupOwner()); | 1454 return axObjectCache().get(frame->pagePopupOwner()); |
1431 } | 1455 } |
1432 | 1456 |
1433 return 0; | 1457 return 0; |
1434 } | 1458 } |
1435 | 1459 |
1436 // | 1460 // |
1437 // Low-level accessibility tree exploration, only for use within the accessibili
ty module. | 1461 // Low-level accessibility tree exploration, only for use within the |
| 1462 // accessibility module. |
1438 // | 1463 // |
1439 | 1464 |
1440 AXObject* AXLayoutObject::rawFirstChild() const { | 1465 AXObject* AXLayoutObject::rawFirstChild() const { |
1441 if (!m_layoutObject) | 1466 if (!m_layoutObject) |
1442 return 0; | 1467 return 0; |
1443 | 1468 |
1444 LayoutObject* firstChild = firstChildConsideringContinuation(m_layoutObject); | 1469 LayoutObject* firstChild = firstChildConsideringContinuation(m_layoutObject); |
1445 | 1470 |
1446 if (!firstChild) | 1471 if (!firstChild) |
1447 return 0; | 1472 return 0; |
1448 | 1473 |
1449 return axObjectCache().getOrCreate(firstChild); | 1474 return axObjectCache().getOrCreate(firstChild); |
1450 } | 1475 } |
1451 | 1476 |
1452 AXObject* AXLayoutObject::rawNextSibling() const { | 1477 AXObject* AXLayoutObject::rawNextSibling() const { |
1453 if (!m_layoutObject) | 1478 if (!m_layoutObject) |
1454 return 0; | 1479 return 0; |
1455 | 1480 |
1456 LayoutObject* nextSibling = 0; | 1481 LayoutObject* nextSibling = 0; |
1457 | 1482 |
1458 LayoutInline* inlineContinuation = | 1483 LayoutInline* inlineContinuation = |
1459 m_layoutObject->isLayoutBlockFlow() | 1484 m_layoutObject->isLayoutBlockFlow() |
1460 ? toLayoutBlockFlow(m_layoutObject)->inlineElementContinuation() | 1485 ? toLayoutBlockFlow(m_layoutObject)->inlineElementContinuation() |
1461 : nullptr; | 1486 : nullptr; |
1462 if (inlineContinuation) { | 1487 if (inlineContinuation) { |
1463 // Case 1: node is a block and has an inline continuation. Next sibling is t
he inline continuation's first child. | 1488 // Case 1: node is a block and has an inline continuation. Next sibling is |
| 1489 // the inline continuation's first child. |
1464 nextSibling = firstChildConsideringContinuation(inlineContinuation); | 1490 nextSibling = firstChildConsideringContinuation(inlineContinuation); |
1465 } else if (m_layoutObject->isAnonymousBlock() && | 1491 } else if (m_layoutObject->isAnonymousBlock() && |
1466 lastChildHasContinuation(m_layoutObject)) { | 1492 lastChildHasContinuation(m_layoutObject)) { |
1467 // Case 2: Anonymous block parent of the start of a continuation - skip all
the way to | 1493 // Case 2: Anonymous block parent of the start of a continuation - skip all |
1468 // after the parent of the end, since everything in between will be linked u
p via the continuation. | 1494 // the way to after the parent of the end, since everything in between will |
| 1495 // be linked up via the continuation. |
1469 LayoutObject* lastParent = | 1496 LayoutObject* lastParent = |
1470 endOfContinuations(toLayoutBlock(m_layoutObject)->lastChild()) | 1497 endOfContinuations(toLayoutBlock(m_layoutObject)->lastChild()) |
1471 ->parent(); | 1498 ->parent(); |
1472 while (lastChildHasContinuation(lastParent)) | 1499 while (lastChildHasContinuation(lastParent)) |
1473 lastParent = endOfContinuations(lastParent->slowLastChild())->parent(); | 1500 lastParent = endOfContinuations(lastParent->slowLastChild())->parent(); |
1474 nextSibling = lastParent->nextSibling(); | 1501 nextSibling = lastParent->nextSibling(); |
1475 } else if (LayoutObject* ns = m_layoutObject->nextSibling()) { | 1502 } else if (LayoutObject* ns = m_layoutObject->nextSibling()) { |
1476 // Case 3: node has an actual next sibling | 1503 // Case 3: node has an actual next sibling |
1477 nextSibling = ns; | 1504 nextSibling = ns; |
1478 } else if (isInlineWithContinuation(m_layoutObject)) { | 1505 } else if (isInlineWithContinuation(m_layoutObject)) { |
1479 // Case 4: node is an inline with a continuation. Next sibling is the next s
ibling of the end | 1506 // Case 4: node is an inline with a continuation. Next sibling is the next |
1480 // of the continuation chain. | 1507 // sibling of the end of the continuation chain. |
1481 nextSibling = endOfContinuations(m_layoutObject)->nextSibling(); | 1508 nextSibling = endOfContinuations(m_layoutObject)->nextSibling(); |
1482 } else if (m_layoutObject->parent() && | 1509 } else if (m_layoutObject->parent() && |
1483 isInlineWithContinuation(m_layoutObject->parent())) { | 1510 isInlineWithContinuation(m_layoutObject->parent())) { |
1484 // Case 5: node has no next sibling, and its parent is an inline with a cont
inuation. | 1511 // Case 5: node has no next sibling, and its parent is an inline with a |
| 1512 // continuation. |
1485 LayoutObject* continuation = | 1513 LayoutObject* continuation = |
1486 toLayoutInline(m_layoutObject->parent())->continuation(); | 1514 toLayoutInline(m_layoutObject->parent())->continuation(); |
1487 | 1515 |
1488 if (continuation->isLayoutBlock()) { | 1516 if (continuation->isLayoutBlock()) { |
1489 // Case 5a: continuation is a block - in this case the block itself is the
next sibling. | 1517 // Case 5a: continuation is a block - in this case the block itself is the |
| 1518 // next sibling. |
1490 nextSibling = continuation; | 1519 nextSibling = continuation; |
1491 } else { | 1520 } else { |
1492 // Case 5b: continuation is an inline - in this case the inline's first ch
ild is the next sibling. | 1521 // Case 5b: continuation is an inline - in this case the inline's first |
| 1522 // child is the next sibling. |
1493 nextSibling = firstChildConsideringContinuation(continuation); | 1523 nextSibling = firstChildConsideringContinuation(continuation); |
1494 } | 1524 } |
1495 } | 1525 } |
1496 | 1526 |
1497 if (!nextSibling) | 1527 if (!nextSibling) |
1498 return 0; | 1528 return 0; |
1499 | 1529 |
1500 return axObjectCache().getOrCreate(nextSibling); | 1530 return axObjectCache().getOrCreate(nextSibling); |
1501 } | 1531 } |
1502 | 1532 |
1503 void AXLayoutObject::addChildren() { | 1533 void AXLayoutObject::addChildren() { |
1504 ASSERT(!isDetached()); | 1534 ASSERT(!isDetached()); |
1505 // If the need to add more children in addition to existing children arises, | 1535 // If the need to add more children in addition to existing children arises, |
1506 // childrenChanged should have been called, leaving the object with no childre
n. | 1536 // childrenChanged should have been called, leaving the object with no |
| 1537 // children. |
1507 ASSERT(!m_haveChildren); | 1538 ASSERT(!m_haveChildren); |
1508 | 1539 |
1509 m_haveChildren = true; | 1540 m_haveChildren = true; |
1510 | 1541 |
1511 if (!canHaveChildren()) | 1542 if (!canHaveChildren()) |
1512 return; | 1543 return; |
1513 | 1544 |
1514 HeapVector<Member<AXObject>> ownedChildren; | 1545 HeapVector<Member<AXObject>> ownedChildren; |
1515 computeAriaOwnsChildren(ownedChildren); | 1546 computeAriaOwnsChildren(ownedChildren); |
1516 | 1547 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1595 return getLayoutObject()->document().view(); | 1626 return getLayoutObject()->document().view(); |
1596 } | 1627 } |
1597 | 1628 |
1598 Element* AXLayoutObject::anchorElement() const { | 1629 Element* AXLayoutObject::anchorElement() const { |
1599 if (!m_layoutObject) | 1630 if (!m_layoutObject) |
1600 return 0; | 1631 return 0; |
1601 | 1632 |
1602 AXObjectCacheImpl& cache = axObjectCache(); | 1633 AXObjectCacheImpl& cache = axObjectCache(); |
1603 LayoutObject* currLayoutObject; | 1634 LayoutObject* currLayoutObject; |
1604 | 1635 |
1605 // Search up the layout tree for a LayoutObject with a DOM node. Defer to an e
arlier continuation, though. | 1636 // Search up the layout tree for a LayoutObject with a DOM node. Defer to an |
| 1637 // earlier continuation, though. |
1606 for (currLayoutObject = m_layoutObject; | 1638 for (currLayoutObject = m_layoutObject; |
1607 currLayoutObject && !currLayoutObject->node(); | 1639 currLayoutObject && !currLayoutObject->node(); |
1608 currLayoutObject = currLayoutObject->parent()) { | 1640 currLayoutObject = currLayoutObject->parent()) { |
1609 if (currLayoutObject->isAnonymousBlock() && | 1641 if (currLayoutObject->isAnonymousBlock() && |
1610 currLayoutObject->isLayoutBlockFlow()) { | 1642 currLayoutObject->isLayoutBlockFlow()) { |
1611 LayoutObject* continuation = | 1643 LayoutObject* continuation = |
1612 toLayoutBlockFlow(currLayoutObject)->continuation(); | 1644 toLayoutBlockFlow(currLayoutObject)->continuation(); |
1613 if (continuation) | 1645 if (continuation) |
1614 return cache.getOrCreate(continuation)->anchorElement(); | 1646 return cache.getOrCreate(continuation)->anchorElement(); |
1615 } | 1647 } |
1616 } | 1648 } |
1617 | 1649 |
1618 // bail if none found | 1650 // bail if none found |
1619 if (!currLayoutObject) | 1651 if (!currLayoutObject) |
1620 return 0; | 1652 return 0; |
1621 | 1653 |
1622 // search up the DOM tree for an anchor element | 1654 // Search up the DOM tree for an anchor element. |
1623 // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElemen
t | 1655 // NOTE: this assumes that any non-image with an anchor is an |
| 1656 // HTMLAnchorElement |
1624 Node* node = currLayoutObject->node(); | 1657 Node* node = currLayoutObject->node(); |
1625 if (!node) | 1658 if (!node) |
1626 return nullptr; | 1659 return nullptr; |
1627 for (Node& runner : NodeTraversal::inclusiveAncestorsOf(*node)) { | 1660 for (Node& runner : NodeTraversal::inclusiveAncestorsOf(*node)) { |
1628 if (isHTMLAnchorElement(runner) || | 1661 if (isHTMLAnchorElement(runner) || |
1629 (runner.layoutObject() && | 1662 (runner.layoutObject() && |
1630 cache.getOrCreate(runner.layoutObject())->isAnchor())) | 1663 cache.getOrCreate(runner.layoutObject())->isAnchor())) |
1631 return toElement(&runner); | 1664 return toElement(&runner); |
1632 } | 1665 } |
1633 | 1666 |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1812 | 1845 |
1813 // Convert from an accessible object and offset to a VisiblePosition. | 1846 // Convert from an accessible object and offset to a VisiblePosition. |
1814 static VisiblePosition toVisiblePosition(AXObject* obj, int offset) { | 1847 static VisiblePosition toVisiblePosition(AXObject* obj, int offset) { |
1815 if (!obj->getNode()) | 1848 if (!obj->getNode()) |
1816 return VisiblePosition(); | 1849 return VisiblePosition(); |
1817 | 1850 |
1818 Node* node = obj->getNode(); | 1851 Node* node = obj->getNode(); |
1819 if (!node->isTextNode()) { | 1852 if (!node->isTextNode()) { |
1820 int childCount = obj->children().size(); | 1853 int childCount = obj->children().size(); |
1821 | 1854 |
1822 // Place position immediately before the container node, if there was no chi
ldren. | 1855 // Place position immediately before the container node, if there was no |
| 1856 // children. |
1823 if (childCount == 0) { | 1857 if (childCount == 0) { |
1824 if (!obj->parentObject()) | 1858 if (!obj->parentObject()) |
1825 return VisiblePosition(); | 1859 return VisiblePosition(); |
1826 return toVisiblePosition(obj->parentObject(), obj->indexInParent()); | 1860 return toVisiblePosition(obj->parentObject(), obj->indexInParent()); |
1827 } | 1861 } |
1828 | 1862 |
1829 // The offsets are child offsets over the AX tree. Note that we allow | 1863 // The offsets are child offsets over the AX tree. Note that we allow |
1830 // for the offset to equal the number of children as |Range| does. | 1864 // for the offset to equal the number of children as |Range| does. |
1831 if (offset < 0 || offset > childCount) | 1865 if (offset < 0 || offset > childCount) |
1832 return VisiblePosition(); | 1866 return VisiblePosition(); |
(...skipping 13 matching lines...) Expand all Loading... |
1846 | 1880 |
1847 // If we had to clamp the offset above, the client wants to select the | 1881 // If we had to clamp the offset above, the client wants to select the |
1848 // end of the node. | 1882 // end of the node. |
1849 if (clampedOffset != offset) | 1883 if (clampedOffset != offset) |
1850 adjustedOffset++; | 1884 adjustedOffset++; |
1851 | 1885 |
1852 return createVisiblePosition( | 1886 return createVisiblePosition( |
1853 Position::editingPositionOf(childNode->parentNode(), adjustedOffset)); | 1887 Position::editingPositionOf(childNode->parentNode(), adjustedOffset)); |
1854 } | 1888 } |
1855 | 1889 |
1856 // If it is a text node, we need to call some utility functions that use a Tex
tIterator | 1890 // If it is a text node, we need to call some utility functions that use a |
1857 // to walk the characters of the node and figure out the position correspondin
g to the | 1891 // TextIterator to walk the characters of the node and figure out the position |
1858 // visible character at position |offset|. | 1892 // corresponding to the visible character at position |offset|. |
1859 ContainerNode* parent = node->parentNode(); | 1893 ContainerNode* parent = node->parentNode(); |
1860 if (!parent) | 1894 if (!parent) |
1861 return VisiblePosition(); | 1895 return VisiblePosition(); |
1862 | 1896 |
1863 VisiblePosition nodePosition = blink::visiblePositionBeforeNode(*node); | 1897 VisiblePosition nodePosition = blink::visiblePositionBeforeNode(*node); |
1864 int nodeIndex = blink::indexForVisiblePosition(nodePosition, parent); | 1898 int nodeIndex = blink::indexForVisiblePosition(nodePosition, parent); |
1865 return blink::visiblePositionForIndex(nodeIndex + offset, parent); | 1899 return blink::visiblePositionForIndex(nodeIndex + offset, parent); |
1866 } | 1900 } |
1867 | 1901 |
1868 void AXLayoutObject::setSelection(const AXRange& selection) { | 1902 void AXLayoutObject::setSelection(const AXRange& selection) { |
(...skipping 25 matching lines...) Expand all Loading... |
1894 selection.anchorOffset, | 1928 selection.anchorOffset, |
1895 SelectionHasBackwardDirection); | 1929 SelectionHasBackwardDirection); |
1896 } | 1930 } |
1897 return; | 1931 return; |
1898 } | 1932 } |
1899 | 1933 |
1900 LocalFrame* frame = getLayoutObject()->frame(); | 1934 LocalFrame* frame = getLayoutObject()->frame(); |
1901 if (!frame) | 1935 if (!frame) |
1902 return; | 1936 return; |
1903 | 1937 |
1904 // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets nee
ds to be audited. | 1938 // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets |
1905 // see http://crbug.com/590369 for more details. | 1939 // needs to be audited. see http://crbug.com/590369 for more details. |
1906 // This callsite should probably move up the stack. | 1940 // This callsite should probably move up the stack. |
1907 frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); | 1941 frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
1908 | 1942 |
1909 // Set the selection based on visible positions, because the offsets in access
ibility nodes | 1943 // Set the selection based on visible positions, because the offsets in |
1910 // are based on visible indexes, which often skips redundant whitespace, for e
xample. | 1944 // accessibility nodes are based on visible indexes, which often skips |
| 1945 // redundant whitespace, for example. |
1911 VisiblePosition anchorVisiblePosition = | 1946 VisiblePosition anchorVisiblePosition = |
1912 toVisiblePosition(anchorObject, selection.anchorOffset); | 1947 toVisiblePosition(anchorObject, selection.anchorOffset); |
1913 VisiblePosition focusVisiblePosition = | 1948 VisiblePosition focusVisiblePosition = |
1914 toVisiblePosition(focusObject, selection.focusOffset); | 1949 toVisiblePosition(focusObject, selection.focusOffset); |
1915 if (anchorVisiblePosition.isNull() || focusVisiblePosition.isNull()) | 1950 if (anchorVisiblePosition.isNull() || focusVisiblePosition.isNull()) |
1916 return; | 1951 return; |
1917 | 1952 |
1918 frame->selection().setSelection( | 1953 frame->selection().setSelection( |
1919 createVisibleSelection(anchorVisiblePosition, focusVisiblePosition)); | 1954 createVisibleSelection(anchorVisiblePosition, focusVisiblePosition)); |
1920 } | 1955 } |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2103 0) | 2138 0) |
2104 break; | 2139 break; |
2105 } | 2140 } |
2106 } | 2141 } |
2107 | 2142 |
2108 // | 2143 // |
2109 // Private. | 2144 // Private. |
2110 // | 2145 // |
2111 | 2146 |
2112 AXObject* AXLayoutObject::treeAncestorDisallowingChild() const { | 2147 AXObject* AXLayoutObject::treeAncestorDisallowingChild() const { |
2113 // Determine if this is in a tree. If so, we apply special behavior to make it
work like an AXOutline. | 2148 // Determine if this is in a tree. If so, we apply special behavior to make it |
| 2149 // work like an AXOutline. |
2114 AXObject* axObj = parentObject(); | 2150 AXObject* axObj = parentObject(); |
2115 AXObject* treeAncestor = 0; | 2151 AXObject* treeAncestor = 0; |
2116 while (axObj) { | 2152 while (axObj) { |
2117 if (axObj->isTree()) { | 2153 if (axObj->isTree()) { |
2118 treeAncestor = axObj; | 2154 treeAncestor = axObj; |
2119 break; | 2155 break; |
2120 } | 2156 } |
2121 axObj = axObj->parentObject(); | 2157 axObj = axObj->parentObject(); |
2122 } | 2158 } |
2123 | 2159 |
2124 // If the object is in a tree, only tree items should be exposed (and the chil
dren of tree items). | 2160 // If the object is in a tree, only tree items should be exposed (and the |
| 2161 // children of tree items). |
2125 if (treeAncestor) { | 2162 if (treeAncestor) { |
2126 AccessibilityRole role = roleValue(); | 2163 AccessibilityRole role = roleValue(); |
2127 if (role != TreeItemRole && role != StaticTextRole) | 2164 if (role != TreeItemRole && role != StaticTextRole) |
2128 return treeAncestor; | 2165 return treeAncestor; |
2129 } | 2166 } |
2130 return 0; | 2167 return 0; |
2131 } | 2168 } |
2132 | 2169 |
2133 bool AXLayoutObject::isTabItemSelected() const { | 2170 bool AXLayoutObject::isTabItemSelected() const { |
2134 if (!isTabItem() || !getLayoutObject()) | 2171 if (!isTabItem() || !getLayoutObject()) |
2135 return false; | 2172 return false; |
2136 | 2173 |
2137 Node* node = getNode(); | 2174 Node* node = getNode(); |
2138 if (!node || !node->isElementNode()) | 2175 if (!node || !node->isElementNode()) |
2139 return false; | 2176 return false; |
2140 | 2177 |
2141 // The ARIA spec says a tab item can also be selected if it is aria-labeled by
a tabpanel | 2178 // The ARIA spec says a tab item can also be selected if it is aria-labeled by |
2142 // that has keyboard focus inside of it, or if a tabpanel in its aria-controls
list has KB | 2179 // a tabpanel that has keyboard focus inside of it, or if a tabpanel in its |
2143 // focus inside of it. | 2180 // aria-controls list has KB focus inside of it. |
2144 AXObject* focusedElement = axObjectCache().focusedObject(); | 2181 AXObject* focusedElement = axObjectCache().focusedObject(); |
2145 if (!focusedElement) | 2182 if (!focusedElement) |
2146 return false; | 2183 return false; |
2147 | 2184 |
2148 HeapVector<Member<Element>> elements; | 2185 HeapVector<Member<Element>> elements; |
2149 elementsFromAttribute(elements, aria_controlsAttr); | 2186 elementsFromAttribute(elements, aria_controlsAttr); |
2150 | 2187 |
2151 for (const auto& element : elements) { | 2188 for (const auto& element : elements) { |
2152 AXObject* tabPanel = axObjectCache().getOrCreate(element); | 2189 AXObject* tabPanel = axObjectCache().getOrCreate(element); |
2153 | 2190 |
2154 // A tab item should only control tab panels. | 2191 // A tab item should only control tab panels. |
2155 if (!tabPanel || tabPanel->roleValue() != TabPanelRole) | 2192 if (!tabPanel || tabPanel->roleValue() != TabPanelRole) |
2156 continue; | 2193 continue; |
2157 | 2194 |
2158 AXObject* checkFocusElement = focusedElement; | 2195 AXObject* checkFocusElement = focusedElement; |
2159 // Check if the focused element is a descendant of the element controlled by
the tab item. | 2196 // Check if the focused element is a descendant of the element controlled by |
| 2197 // the tab item. |
2160 while (checkFocusElement) { | 2198 while (checkFocusElement) { |
2161 if (tabPanel == checkFocusElement) | 2199 if (tabPanel == checkFocusElement) |
2162 return true; | 2200 return true; |
2163 checkFocusElement = checkFocusElement->parentObject(); | 2201 checkFocusElement = checkFocusElement->parentObject(); |
2164 } | 2202 } |
2165 } | 2203 } |
2166 | 2204 |
2167 return false; | 2205 return false; |
2168 } | 2206 } |
2169 | 2207 |
(...skipping 25 matching lines...) Expand all Loading... |
2195 if (startOfConts) { | 2233 if (startOfConts) { |
2196 // Case 1: node is a block and is an inline's continuation. Parent | 2234 // Case 1: node is a block and is an inline's continuation. Parent |
2197 // is the start of the continuation chain. | 2235 // is the start of the continuation chain. |
2198 return startOfConts; | 2236 return startOfConts; |
2199 } | 2237 } |
2200 | 2238 |
2201 LayoutObject* parent = m_layoutObject->parent(); | 2239 LayoutObject* parent = m_layoutObject->parent(); |
2202 startOfConts = | 2240 startOfConts = |
2203 parent && parent->isLayoutInline() ? startOfContinuations(parent) : 0; | 2241 parent && parent->isLayoutInline() ? startOfContinuations(parent) : 0; |
2204 if (startOfConts) { | 2242 if (startOfConts) { |
2205 // Case 2: node's parent is an inline which is some node's continuation; par
ent is | 2243 // Case 2: node's parent is an inline which is some node's continuation; |
2206 // the earliest node in the continuation chain. | 2244 // parent is the earliest node in the continuation chain. |
2207 return startOfConts; | 2245 return startOfConts; |
2208 } | 2246 } |
2209 | 2247 |
2210 LayoutObject* firstChild = parent ? parent->slowFirstChild() : 0; | 2248 LayoutObject* firstChild = parent ? parent->slowFirstChild() : 0; |
2211 if (firstChild && firstChild->node()) { | 2249 if (firstChild && firstChild->node()) { |
2212 // Case 3: The first sibling is the beginning of a continuation chain. Find
the origin of that continuation. | 2250 // Case 3: The first sibling is the beginning of a continuation chain. Find |
2213 // Get the node's layoutObject and follow that continuation chain until the
first child is found. | 2251 // the origin of that continuation. Get the node's layoutObject and follow |
| 2252 // that continuation chain until the first child is found. |
2214 for (LayoutObject* nodeLayoutFirstChild = | 2253 for (LayoutObject* nodeLayoutFirstChild = |
2215 firstChild->node()->layoutObject(); | 2254 firstChild->node()->layoutObject(); |
2216 nodeLayoutFirstChild != firstChild; | 2255 nodeLayoutFirstChild != firstChild; |
2217 nodeLayoutFirstChild = firstChild->node()->layoutObject()) { | 2256 nodeLayoutFirstChild = firstChild->node()->layoutObject()) { |
2218 for (LayoutObject* contsTest = nodeLayoutFirstChild; contsTest; | 2257 for (LayoutObject* contsTest = nodeLayoutFirstChild; contsTest; |
2219 contsTest = nextContinuation(contsTest)) { | 2258 contsTest = nextContinuation(contsTest)) { |
2220 if (contsTest == firstChild) { | 2259 if (contsTest == firstChild) { |
2221 parent = nodeLayoutFirstChild->parent(); | 2260 parent = nodeLayoutFirstChild->parent(); |
2222 break; | 2261 break; |
2223 } | 2262 } |
(...skipping 13 matching lines...) Expand all Loading... |
2237 bool AXLayoutObject::isSVGImage() const { | 2276 bool AXLayoutObject::isSVGImage() const { |
2238 return remoteSVGRootElement(); | 2277 return remoteSVGRootElement(); |
2239 } | 2278 } |
2240 | 2279 |
2241 void AXLayoutObject::detachRemoteSVGRoot() { | 2280 void AXLayoutObject::detachRemoteSVGRoot() { |
2242 if (AXSVGRoot* root = remoteSVGRootElement()) | 2281 if (AXSVGRoot* root = remoteSVGRootElement()) |
2243 root->setParent(0); | 2282 root->setParent(0); |
2244 } | 2283 } |
2245 | 2284 |
2246 AXSVGRoot* AXLayoutObject::remoteSVGRootElement() const { | 2285 AXSVGRoot* AXLayoutObject::remoteSVGRootElement() const { |
2247 // FIXME(dmazzoni): none of this code properly handled multiple references to
the same | 2286 // FIXME(dmazzoni): none of this code properly handled multiple references to |
2248 // remote SVG document. I'm disabling this support until it can be fixed prope
rly. | 2287 // the same remote SVG document. I'm disabling this support until it can be |
| 2288 // fixed properly. |
2249 return 0; | 2289 return 0; |
2250 } | 2290 } |
2251 | 2291 |
2252 AXObject* AXLayoutObject::remoteSVGElementHitTest(const IntPoint& point) const { | 2292 AXObject* AXLayoutObject::remoteSVGElementHitTest(const IntPoint& point) const { |
2253 AXObject* remote = remoteSVGRootElement(); | 2293 AXObject* remote = remoteSVGRootElement(); |
2254 if (!remote) | 2294 if (!remote) |
2255 return 0; | 2295 return 0; |
2256 | 2296 |
2257 IntSize offset = | 2297 IntSize offset = |
2258 point - roundedIntPoint(getBoundsInFrameCoordinates().location()); | 2298 point - roundedIntPoint(getBoundsInFrameCoordinates().location()); |
2259 return remote->accessibilityHitTest(IntPoint(offset)); | 2299 return remote->accessibilityHitTest(IntPoint(offset)); |
2260 } | 2300 } |
2261 | 2301 |
2262 // The boundingBox for elements within the remote SVG element needs to be offset
by its position | 2302 // The boundingBox for elements within the remote SVG element needs to be offset |
2263 // within the parent page, otherwise they are in relative coordinates only. | 2303 // by its position within the parent page, otherwise they are in relative |
| 2304 // coordinates only. |
2264 void AXLayoutObject::offsetBoundingBoxForRemoteSVGElement( | 2305 void AXLayoutObject::offsetBoundingBoxForRemoteSVGElement( |
2265 LayoutRect& rect) const { | 2306 LayoutRect& rect) const { |
2266 for (AXObject* parent = parentObject(); parent; | 2307 for (AXObject* parent = parentObject(); parent; |
2267 parent = parent->parentObject()) { | 2308 parent = parent->parentObject()) { |
2268 if (parent->isAXSVGRoot()) { | 2309 if (parent->isAXSVGRoot()) { |
2269 rect.moveBy( | 2310 rect.moveBy( |
2270 parent->parentObject()->getBoundsInFrameCoordinates().location()); | 2311 parent->parentObject()->getBoundsInFrameCoordinates().location()); |
2271 break; | 2312 break; |
2272 } | 2313 } |
2273 } | 2314 } |
2274 } | 2315 } |
2275 | 2316 |
2276 // Hidden children are those that are not laid out or visible, but are specifica
lly marked as aria-hidden=false, | 2317 // Hidden children are those that are not laid out or visible, but are |
| 2318 // specifically marked as aria-hidden=false, |
2277 // meaning that they should be exposed to the AX hierarchy. | 2319 // meaning that they should be exposed to the AX hierarchy. |
2278 void AXLayoutObject::addHiddenChildren() { | 2320 void AXLayoutObject::addHiddenChildren() { |
2279 Node* node = this->getNode(); | 2321 Node* node = this->getNode(); |
2280 if (!node) | 2322 if (!node) |
2281 return; | 2323 return; |
2282 | 2324 |
2283 // First do a quick run through to determine if we have any hidden nodes (most
often we will not). | 2325 // First do a quick run through to determine if we have any hidden nodes (most |
2284 // If we do have hidden nodes, we need to determine where to insert them so th
ey match DOM order as close as possible. | 2326 // often we will not). If we do have hidden nodes, we need to determine where |
| 2327 // to insert them so they match DOM order as close as possible. |
2285 bool shouldInsertHiddenNodes = false; | 2328 bool shouldInsertHiddenNodes = false; |
2286 for (Node& child : NodeTraversal::childrenOf(*node)) { | 2329 for (Node& child : NodeTraversal::childrenOf(*node)) { |
2287 if (!child.layoutObject() && isNodeAriaVisible(&child)) { | 2330 if (!child.layoutObject() && isNodeAriaVisible(&child)) { |
2288 shouldInsertHiddenNodes = true; | 2331 shouldInsertHiddenNodes = true; |
2289 break; | 2332 break; |
2290 } | 2333 } |
2291 } | 2334 } |
2292 | 2335 |
2293 if (!shouldInsertHiddenNodes) | 2336 if (!shouldInsertHiddenNodes) |
2294 return; | 2337 return; |
2295 | 2338 |
2296 // Iterate through all of the children, including those that may have already
been added, and | 2339 // Iterate through all of the children, including those that may have already |
2297 // try to insert hidden nodes in the correct place in the DOM order. | 2340 // been added, and try to insert hidden nodes in the correct place in the DOM |
| 2341 // order. |
2298 unsigned insertionIndex = 0; | 2342 unsigned insertionIndex = 0; |
2299 for (Node& child : NodeTraversal::childrenOf(*node)) { | 2343 for (Node& child : NodeTraversal::childrenOf(*node)) { |
2300 if (child.layoutObject()) { | 2344 if (child.layoutObject()) { |
2301 // Find out where the last layout sibling is located within m_children. | 2345 // Find out where the last layout sibling is located within m_children. |
2302 if (AXObject* childObject = axObjectCache().get(child.layoutObject())) { | 2346 if (AXObject* childObject = axObjectCache().get(child.layoutObject())) { |
2303 if (childObject->accessibilityIsIgnored()) { | 2347 if (childObject->accessibilityIsIgnored()) { |
2304 const auto& children = childObject->children(); | 2348 const auto& children = childObject->children(); |
2305 childObject = children.size() ? children.last().get() : 0; | 2349 childObject = children.size() ? children.last().get() : 0; |
2306 } | 2350 } |
2307 if (childObject) | 2351 if (childObject) |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2362 else | 2406 else |
2363 axObjectCache().remove(areaObject->axObjectID()); | 2407 axObjectCache().remove(areaObject->axObjectID()); |
2364 } | 2408 } |
2365 } | 2409 } |
2366 } | 2410 } |
2367 | 2411 |
2368 void AXLayoutObject::addCanvasChildren() { | 2412 void AXLayoutObject::addCanvasChildren() { |
2369 if (!isHTMLCanvasElement(getNode())) | 2413 if (!isHTMLCanvasElement(getNode())) |
2370 return; | 2414 return; |
2371 | 2415 |
2372 // If it's a canvas, it won't have laid out children, but it might have access
ible fallback content. | 2416 // If it's a canvas, it won't have laid out children, but it might have |
2373 // Clear m_haveChildren because AXNodeObject::addChildren will expect it to be
false. | 2417 // accessible fallback content. Clear m_haveChildren because |
| 2418 // AXNodeObject::addChildren will expect it to be false. |
2374 ASSERT(!m_children.size()); | 2419 ASSERT(!m_children.size()); |
2375 m_haveChildren = false; | 2420 m_haveChildren = false; |
2376 AXNodeObject::addChildren(); | 2421 AXNodeObject::addChildren(); |
2377 } | 2422 } |
2378 | 2423 |
2379 void AXLayoutObject::addPopupChildren() { | 2424 void AXLayoutObject::addPopupChildren() { |
2380 if (!isHTMLInputElement(getNode())) | 2425 if (!isHTMLInputElement(getNode())) |
2381 return; | 2426 return; |
2382 if (AXObject* axPopup = toHTMLInputElement(getNode())->popupRootAXObject()) | 2427 if (AXObject* axPopup = toHTMLInputElement(getNode())->popupRootAXObject()) |
2383 m_children.append(axPopup); | 2428 m_children.append(axPopup); |
(...skipping 16 matching lines...) Expand all Loading... |
2400 | 2445 |
2401 bool AXLayoutObject::elementAttributeValue( | 2446 bool AXLayoutObject::elementAttributeValue( |
2402 const QualifiedName& attributeName) const { | 2447 const QualifiedName& attributeName) const { |
2403 if (!m_layoutObject) | 2448 if (!m_layoutObject) |
2404 return false; | 2449 return false; |
2405 | 2450 |
2406 return equalIgnoringCase(getAttribute(attributeName), "true"); | 2451 return equalIgnoringCase(getAttribute(attributeName), "true"); |
2407 } | 2452 } |
2408 | 2453 |
2409 } // namespace blink | 2454 } // namespace blink |
OLD | NEW |