| 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 23 matching lines...) Expand all Loading... |
| 34 #include "core/dom/ElementTraversal.h" | 34 #include "core/dom/ElementTraversal.h" |
| 35 #include "core/dom/Range.h" | 35 #include "core/dom/Range.h" |
| 36 #include "core/dom/shadow/ShadowRoot.h" | 36 #include "core/dom/shadow/ShadowRoot.h" |
| 37 #include "core/editing/EditingUtilities.h" | 37 #include "core/editing/EditingUtilities.h" |
| 38 #include "core/editing/FrameSelection.h" | 38 #include "core/editing/FrameSelection.h" |
| 39 #include "core/editing/RenderedPosition.h" | 39 #include "core/editing/RenderedPosition.h" |
| 40 #include "core/editing/TextAffinity.h" | 40 #include "core/editing/TextAffinity.h" |
| 41 #include "core/editing/VisibleUnits.h" | 41 #include "core/editing/VisibleUnits.h" |
| 42 #include "core/editing/iterators/CharacterIterator.h" | 42 #include "core/editing/iterators/CharacterIterator.h" |
| 43 #include "core/editing/iterators/TextIterator.h" | 43 #include "core/editing/iterators/TextIterator.h" |
| 44 #include "core/frame/FrameOwner.h" |
| 44 #include "core/frame/FrameView.h" | 45 #include "core/frame/FrameView.h" |
| 45 #include "core/frame/LocalFrame.h" | 46 #include "core/frame/LocalFrame.h" |
| 46 #include "core/frame/Settings.h" | 47 #include "core/frame/Settings.h" |
| 48 #include "core/html/HTMLFrameOwnerElement.h" |
| 47 #include "core/html/HTMLImageElement.h" | 49 #include "core/html/HTMLImageElement.h" |
| 48 #include "core/html/HTMLLabelElement.h" | 50 #include "core/html/HTMLLabelElement.h" |
| 49 #include "core/html/HTMLOptionElement.h" | 51 #include "core/html/HTMLOptionElement.h" |
| 50 #include "core/html/HTMLSelectElement.h" | 52 #include "core/html/HTMLSelectElement.h" |
| 51 #include "core/html/HTMLTextAreaElement.h" | 53 #include "core/html/HTMLTextAreaElement.h" |
| 52 #include "core/html/shadow/ShadowElementNames.h" | 54 #include "core/html/shadow/ShadowElementNames.h" |
| 53 #include "core/layout/HitTestResult.h" | 55 #include "core/layout/HitTestResult.h" |
| 54 #include "core/layout/LayoutFieldset.h" | 56 #include "core/layout/LayoutFieldset.h" |
| 55 #include "core/layout/LayoutFileUploadControl.h" | 57 #include "core/layout/LayoutFileUploadControl.h" |
| 56 #include "core/layout/LayoutHTMLCanvas.h" | 58 #include "core/layout/LayoutHTMLCanvas.h" |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 if (m_layoutObject) | 341 if (m_layoutObject) |
| 340 m_layoutObject->setHasAXObject(false); | 342 m_layoutObject->setHasAXObject(false); |
| 341 #endif | 343 #endif |
| 342 m_layoutObject = 0; | 344 m_layoutObject = 0; |
| 343 } | 345 } |
| 344 | 346 |
| 345 // | 347 // |
| 346 // Check object role or purpose. | 348 // Check object role or purpose. |
| 347 // | 349 // |
| 348 | 350 |
| 349 bool AXLayoutObject::isAttachment() const | |
| 350 { | |
| 351 LayoutBoxModelObject* layoutObject = layoutBoxModelObject(); | |
| 352 if (!layoutObject) | |
| 353 return false; | |
| 354 // Widgets are the replaced elements that we represent to AX as attachments | |
| 355 bool isLayoutPart = layoutObject->isLayoutPart(); | |
| 356 ASSERT(!isLayoutPart || (layoutObject->isAtomicInlineLevel() && !isImage()))
; | |
| 357 return isLayoutPart; | |
| 358 } | |
| 359 | |
| 360 static bool isLinkable(const AXObject& object) | 351 static bool isLinkable(const AXObject& object) |
| 361 { | 352 { |
| 362 if (!object.layoutObject()) | 353 if (!object.layoutObject()) |
| 363 return false; | 354 return false; |
| 364 | 355 |
| 365 // See https://wiki.mozilla.org/Accessibility/AT-Windows-API for the element
s | 356 // See https://wiki.mozilla.org/Accessibility/AT-Windows-API for the element
s |
| 366 // Mozilla considers linkable. | 357 // Mozilla considers linkable. |
| 367 return object.isLink() || object.isImage() || object.layoutObject()->isText(
); | 358 return object.isLink() || object.isImage() || object.layoutObject()->isText(
); |
| 368 } | 359 } |
| 369 | 360 |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 return true; | 559 return true; |
| 569 } | 560 } |
| 570 | 561 |
| 571 // An ARIA tree can only have tree items and static text as children. | 562 // An ARIA tree can only have tree items and static text as children. |
| 572 if (AXObject* treeAncestor = treeAncestorDisallowingChild()) { | 563 if (AXObject* treeAncestor = treeAncestorDisallowingChild()) { |
| 573 if (ignoredReasons) | 564 if (ignoredReasons) |
| 574 ignoredReasons->append(IgnoredReason(AXAncestorDisallowsChild, treeA
ncestor)); | 565 ignoredReasons->append(IgnoredReason(AXAncestorDisallowsChild, treeA
ncestor)); |
| 575 return true; | 566 return true; |
| 576 } | 567 } |
| 577 | 568 |
| 578 // TODO: we should refactor this - but right now this is necessary to make | 569 // A LayoutPart is an iframe element or embedded object element or something
like |
| 579 // sure scroll areas stay in the tree. | 570 // that. We don't want to ignore those. |
| 580 if (isAttachment()) | 571 if (m_layoutObject->isLayoutPart()) |
| 581 return false; | 572 return false; |
| 582 | 573 |
| 583 // find out if this element is inside of a label element. | 574 // find out if this element is inside of a label element. |
| 584 // if so, it may be ignored because it's the label for a checkbox or radio b
utton | 575 // if so, it may be ignored because it's the label for a checkbox or radio b
utton |
| 585 AXObject* controlObject = correspondingControlForLabelElement(); | 576 AXObject* controlObject = correspondingControlForLabelElement(); |
| 586 if (controlObject && controlObject->isCheckboxOrRadio() && controlObject->na
meFromLabelElement()) { | 577 if (controlObject && controlObject->isCheckboxOrRadio() && controlObject->na
meFromLabelElement()) { |
| 587 if (ignoredReasons) { | 578 if (ignoredReasons) { |
| 588 HTMLLabelElement* label = labelElementContainer(); | 579 HTMLLabelElement* label = labelElementContainer(); |
| 589 if (label && !label->isSameNode(node())) { | 580 if (label && !label->isSameNode(node())) { |
| 590 AXObject* labelAXObject = axObjectCache().getOrCreate(label); | 581 AXObject* labelAXObject = axObjectCache().getOrCreate(label); |
| (...skipping 928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1519 if (ariaRoleAttribute() == MenuRole) { | 1510 if (ariaRoleAttribute() == MenuRole) { |
| 1520 AXObject* parent = menuButtonForMenu(); | 1511 AXObject* parent = menuButtonForMenu(); |
| 1521 if (parent) | 1512 if (parent) |
| 1522 return parent; | 1513 return parent; |
| 1523 } | 1514 } |
| 1524 | 1515 |
| 1525 LayoutObject* parentObj = layoutParentObject(); | 1516 LayoutObject* parentObj = layoutParentObject(); |
| 1526 if (parentObj) | 1517 if (parentObj) |
| 1527 return axObjectCache().getOrCreate(parentObj); | 1518 return axObjectCache().getOrCreate(parentObj); |
| 1528 | 1519 |
| 1529 // WebArea's parent should be the scroll view containing it. | 1520 // A WebArea's parent should be the containing frame (if local) or page popu
p owner. |
| 1530 if (isWebArea()) | 1521 if (isWebArea()) { |
| 1531 return axObjectCache().getOrCreate(m_layoutObject->frame()->view()); | 1522 LocalFrame* frame = m_layoutObject->frame(); |
| 1523 if (frame->owner() && frame->owner()->isLocal()) { |
| 1524 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(frame->owner(
)); |
| 1525 if (owner && owner->layoutObject()) |
| 1526 return axObjectCache().getOrCreate(owner->layoutObject()); |
| 1527 } |
| 1528 return axObjectCache().getOrCreate(frame->pagePopupOwner()); |
| 1529 } |
| 1532 | 1530 |
| 1533 return 0; | 1531 return 0; |
| 1534 } | 1532 } |
| 1535 | 1533 |
| 1536 AXObject* AXLayoutObject::computeParentIfExists() const | 1534 AXObject* AXLayoutObject::computeParentIfExists() const |
| 1537 { | 1535 { |
| 1538 if (!m_layoutObject) | 1536 if (!m_layoutObject) |
| 1539 return 0; | 1537 return 0; |
| 1540 | 1538 |
| 1541 if (ariaRoleAttribute() == MenuBarRole) | 1539 if (ariaRoleAttribute() == MenuBarRole) |
| 1542 return axObjectCache().get(m_layoutObject->parent()); | 1540 return axObjectCache().get(m_layoutObject->parent()); |
| 1543 | 1541 |
| 1544 // menuButton and its corresponding menu are DOM siblings, but Accessibility
needs them to be parent/child | 1542 // menuButton and its corresponding menu are DOM siblings, but Accessibility
needs them to be parent/child |
| 1545 if (ariaRoleAttribute() == MenuRole) { | 1543 if (ariaRoleAttribute() == MenuRole) { |
| 1546 AXObject* parent = menuButtonForMenu(); | 1544 AXObject* parent = menuButtonForMenu(); |
| 1547 if (parent) | 1545 if (parent) |
| 1548 return parent; | 1546 return parent; |
| 1549 } | 1547 } |
| 1550 | 1548 |
| 1551 LayoutObject* parentObj = layoutParentObject(); | 1549 LayoutObject* parentObj = layoutParentObject(); |
| 1552 if (parentObj) | 1550 if (parentObj) |
| 1553 return axObjectCache().get(parentObj); | 1551 return axObjectCache().get(parentObj); |
| 1554 | 1552 |
| 1555 // WebArea's parent should be the scroll view containing it. | 1553 // A WebArea's parent should be the containing frame (if local) or page popu
p owner. |
| 1556 if (isWebArea()) | 1554 if (isWebArea()) { |
| 1557 return axObjectCache().get(m_layoutObject->frame()->view()); | 1555 LocalFrame* frame = m_layoutObject->frame(); |
| 1556 if (frame->owner() && frame->owner()->isLocal()) { |
| 1557 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(frame->owner(
)); |
| 1558 if (owner && owner->layoutObject()) |
| 1559 return axObjectCache().get(owner->layoutObject()); |
| 1560 } |
| 1561 return axObjectCache().get(frame->pagePopupOwner()); |
| 1562 } |
| 1558 | 1563 |
| 1559 return 0; | 1564 return 0; |
| 1560 } | 1565 } |
| 1561 | 1566 |
| 1562 // | 1567 // |
| 1563 // Low-level accessibility tree exploration, only for use within the accessibili
ty module. | 1568 // Low-level accessibility tree exploration, only for use within the accessibili
ty module. |
| 1564 // | 1569 // |
| 1565 | 1570 |
| 1566 AXObject* AXLayoutObject::rawFirstChild() const | 1571 AXObject* AXLayoutObject::rawFirstChild() const |
| 1567 { | 1572 { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1636 computeAriaOwnsChildren(ownedChildren); | 1641 computeAriaOwnsChildren(ownedChildren); |
| 1637 | 1642 |
| 1638 for (AXObject* obj = rawFirstChild(); obj; obj = obj->rawNextSibling()) { | 1643 for (AXObject* obj = rawFirstChild(); obj; obj = obj->rawNextSibling()) { |
| 1639 if (!axObjectCache().isAriaOwned(obj)) { | 1644 if (!axObjectCache().isAriaOwned(obj)) { |
| 1640 obj->setParent(this); | 1645 obj->setParent(this); |
| 1641 addChild(obj); | 1646 addChild(obj); |
| 1642 } | 1647 } |
| 1643 } | 1648 } |
| 1644 | 1649 |
| 1645 addHiddenChildren(); | 1650 addHiddenChildren(); |
| 1646 addAttachmentChildren(); | 1651 addFrameChildren(); |
| 1647 addPopupChildren(); | 1652 addPopupChildren(); |
| 1648 addImageMapChildren(); | 1653 addImageMapChildren(); |
| 1649 addTextFieldChildren(); | 1654 addTextFieldChildren(); |
| 1650 addCanvasChildren(); | 1655 addCanvasChildren(); |
| 1651 addRemoteSVGChildren(); | 1656 addRemoteSVGChildren(); |
| 1652 addInlineTextBoxChildren(false); | 1657 addInlineTextBoxChildren(false); |
| 1653 | 1658 |
| 1654 for (const auto& child : m_children) { | 1659 for (const auto& child : m_children) { |
| 1655 if (!child->cachedParentObject()) | 1660 if (!child->cachedParentObject()) |
| 1656 child->setParent(this); | 1661 child->setParent(this); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1749 // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElem
ent | 1754 // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElem
ent |
| 1750 Node* node = currLayoutObject->node(); | 1755 Node* node = currLayoutObject->node(); |
| 1751 for ( ; node; node = node->parentNode()) { | 1756 for ( ; node; node = node->parentNode()) { |
| 1752 if (isHTMLAnchorElement(*node) || (node->layoutObject() && cache.getOrCr
eate(node->layoutObject())->isAnchor())) | 1757 if (isHTMLAnchorElement(*node) || (node->layoutObject() && cache.getOrCr
eate(node->layoutObject())->isAnchor())) |
| 1753 return toElement(node); | 1758 return toElement(node); |
| 1754 } | 1759 } |
| 1755 | 1760 |
| 1756 return 0; | 1761 return 0; |
| 1757 } | 1762 } |
| 1758 | 1763 |
| 1759 Widget* AXLayoutObject::widgetForAttachmentView() const | |
| 1760 { | |
| 1761 if (!isAttachment()) | |
| 1762 return 0; | |
| 1763 return toLayoutPart(m_layoutObject)->widget(); | |
| 1764 } | |
| 1765 | |
| 1766 // | 1764 // |
| 1767 // Functions that retrieve the current selection. | 1765 // Functions that retrieve the current selection. |
| 1768 // | 1766 // |
| 1769 | 1767 |
| 1770 AXObject::AXRange AXLayoutObject::selection() const | 1768 AXObject::AXRange AXLayoutObject::selection() const |
| 1771 { | 1769 { |
| 1772 AXRange textSelection = textControlSelection(); | 1770 AXRange textSelection = textControlSelection(); |
| 1773 if (textSelection.isValid()) | 1771 if (textSelection.isValid()) |
| 1774 return textSelection; | 1772 return textSelection; |
| 1775 | 1773 |
| (...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2432 if (!isHTMLCanvasElement(node())) | 2430 if (!isHTMLCanvasElement(node())) |
| 2433 return; | 2431 return; |
| 2434 | 2432 |
| 2435 // If it's a canvas, it won't have laid out children, but it might have acce
ssible fallback content. | 2433 // If it's a canvas, it won't have laid out children, but it might have acce
ssible fallback content. |
| 2436 // Clear m_haveChildren because AXNodeObject::addChildren will expect it to
be false. | 2434 // Clear m_haveChildren because AXNodeObject::addChildren will expect it to
be false. |
| 2437 ASSERT(!m_children.size()); | 2435 ASSERT(!m_children.size()); |
| 2438 m_haveChildren = false; | 2436 m_haveChildren = false; |
| 2439 AXNodeObject::addChildren(); | 2437 AXNodeObject::addChildren(); |
| 2440 } | 2438 } |
| 2441 | 2439 |
| 2442 void AXLayoutObject::addAttachmentChildren() | 2440 void AXLayoutObject::addFrameChildren() |
| 2443 { | 2441 { |
| 2444 if (!isAttachment()) | 2442 if (!m_layoutObject || !m_layoutObject->isLayoutPart()) |
| 2445 return; | 2443 return; |
| 2446 | 2444 |
| 2447 // FrameView's need to be inserted into the AX hierarchy when encountered. | 2445 Widget* widget = toLayoutPart(m_layoutObject)->widget(); |
| 2448 Widget* widget = widgetForAttachmentView(); | |
| 2449 if (!widget || !widget->isFrameView()) | 2446 if (!widget || !widget->isFrameView()) |
| 2450 return; | 2447 return; |
| 2451 | 2448 |
| 2452 AXObject* axWidget = axObjectCache().getOrCreate(widget); | 2449 Document* doc = toFrameView(widget)->frame().document(); |
| 2453 if (!axWidget->accessibilityIsIgnored()) | 2450 if (!doc || !doc->layoutView()) |
| 2454 m_children.append(axWidget); | 2451 return; |
| 2452 |
| 2453 AXObject* axChildFrame = axObjectCache().getOrCreate(doc); |
| 2454 if (!axChildFrame->accessibilityIsIgnored()) |
| 2455 m_children.append(axChildFrame); |
| 2455 } | 2456 } |
| 2456 | 2457 |
| 2457 void AXLayoutObject::addPopupChildren() | 2458 void AXLayoutObject::addPopupChildren() |
| 2458 { | 2459 { |
| 2459 if (!isHTMLInputElement(node())) | 2460 if (!isHTMLInputElement(node())) |
| 2460 return; | 2461 return; |
| 2461 if (AXObject* axPopup = toHTMLInputElement(node())->popupRootAXObject()) | 2462 if (AXObject* axPopup = toHTMLInputElement(node())->popupRootAXObject()) |
| 2462 m_children.append(axPopup); | 2463 m_children.append(axPopup); |
| 2463 } | 2464 } |
| 2464 | 2465 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2530 if (label && label->layoutObject()) { | 2531 if (label && label->layoutObject()) { |
| 2531 LayoutRect labelRect = axObjectCache().getOrCreate(label)->elementRe
ct(); | 2532 LayoutRect labelRect = axObjectCache().getOrCreate(label)->elementRe
ct(); |
| 2532 result.unite(labelRect); | 2533 result.unite(labelRect); |
| 2533 } | 2534 } |
| 2534 } | 2535 } |
| 2535 | 2536 |
| 2536 return result; | 2537 return result; |
| 2537 } | 2538 } |
| 2538 | 2539 |
| 2539 } // namespace blink | 2540 } // namespace blink |
| OLD | NEW |