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 |