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

Side by Side Diff: third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp

Issue 2393003002: reflow comments in modules/accessiblity (Closed)
Patch Set: Created 4 years, 2 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 /* 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698