HTMLLinkAccessible.cpp (4501B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "HTMLLinkAccessible.h" 7 8 #include "CacheConstants.h" 9 #include "nsCoreUtils.h" 10 #include "mozilla/a11y/Role.h" 11 #include "States.h" 12 13 #include "nsContentUtils.h" 14 #include "nsIMutationObserver.h" 15 #include "mozilla/a11y/DocAccessible.h" 16 #include "mozilla/dom/Element.h" 17 18 using namespace mozilla; 19 using namespace mozilla::a11y; 20 21 //////////////////////////////////////////////////////////////////////////////// 22 // HTMLLinkAccessible 23 //////////////////////////////////////////////////////////////////////////////// 24 25 HTMLLinkAccessible::HTMLLinkAccessible(nsIContent* aContent, 26 DocAccessible* aDoc) 27 : HyperTextAccessible(aContent, aDoc) { 28 mType = eHTMLLinkType; 29 } 30 31 //////////////////////////////////////////////////////////////////////////////// 32 // nsIAccessible 33 34 role HTMLLinkAccessible::NativeRole() const { return roles::LINK; } 35 36 uint64_t HTMLLinkAccessible::NativeState() const { 37 return HyperTextAccessible::NativeState() & ~states::READONLY; 38 } 39 40 uint64_t HTMLLinkAccessible::NativeLinkState() const { 41 dom::ElementState state = mContent->AsElement()->State(); 42 if (state.HasState(dom::ElementState::UNVISITED)) { 43 return states::LINKED; 44 } 45 46 if (state.HasState(dom::ElementState::VISITED)) { 47 return states::LINKED | states::TRAVERSED; 48 } 49 50 // This is a either named anchor (a link with also a name attribute) or 51 // it doesn't have any attributes. Check if 'click' event handler is 52 // registered, otherwise bail out. 53 return nsCoreUtils::HasClickListener(mContent) ? states::LINKED : 0; 54 } 55 56 uint64_t HTMLLinkAccessible::NativeInteractiveState() const { 57 uint64_t state = HyperTextAccessible::NativeInteractiveState(); 58 59 // This is how we indicate it is a named anchor. In other words, this anchor 60 // can be selected as a location :) There is no other better state to use to 61 // indicate this. 62 if (mContent->AsElement()->HasAttr(nsGkAtoms::name)) { 63 state |= states::SELECTABLE; 64 } 65 66 return state; 67 } 68 69 void HTMLLinkAccessible::Value(nsString& aValue) const { 70 aValue.Truncate(); 71 72 HyperTextAccessible::Value(aValue); 73 if (aValue.IsEmpty()) { 74 nsContentUtils::GetLinkLocation(mContent->AsElement(), aValue); 75 } 76 } 77 78 bool HTMLLinkAccessible::HasPrimaryAction() const { 79 return IsLinked() || HyperTextAccessible::HasPrimaryAction(); 80 ; 81 } 82 83 void HTMLLinkAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) { 84 aName.Truncate(); 85 86 if (!IsLinked()) { 87 HyperTextAccessible::ActionNameAt(aIndex, aName); 88 return; 89 } 90 91 // Action 0 (default action): Jump to link 92 if (aIndex == eAction_Jump) aName.AssignLiteral("jump"); 93 } 94 95 bool HTMLLinkAccessible::AttributeChangesState(nsAtom* aAttribute) { 96 return aAttribute == nsGkAtoms::href || 97 HyperTextAccessible::AttributeChangesState(aAttribute); 98 } 99 100 void HTMLLinkAccessible::DOMAttributeChanged(int32_t aNameSpaceID, 101 nsAtom* aAttribute, 102 AttrModType aModType, 103 const nsAttrValue* aOldValue, 104 uint64_t aOldState) { 105 HyperTextAccessible::DOMAttributeChanged(aNameSpaceID, aAttribute, aModType, 106 aOldValue, aOldState); 107 108 if (aAttribute == nsGkAtoms::href && IsAdditionOrRemoval(aModType)) { 109 mDoc->QueueCacheUpdate(this, CacheDomain::Actions); 110 } 111 } 112 113 ENameValueFlag HTMLLinkAccessible::NativeName(nsString& aName) const { 114 if (mContent->IsSVGElement()) { 115 mContent->AsElement()->GetAttr(kNameSpaceID_XLink, nsGkAtoms::title, aName); 116 if (!aName.IsEmpty()) { 117 return eNameOK; 118 } 119 } 120 121 return HyperTextAccessible::NativeName(aName); 122 } 123 124 //////////////////////////////////////////////////////////////////////////////// 125 // HyperLinkAccessible 126 127 bool HTMLLinkAccessible::IsLink() const { 128 // Expose HyperLinkAccessible unconditionally. 129 return true; 130 } 131 132 //////////////////////////////////////////////////////////////////////////////// 133 // HTMLLinkAccessible 134 135 bool HTMLLinkAccessible::IsLinked() const { 136 dom::ElementState state = mContent->AsElement()->State(); 137 return state.HasAtLeastOneOfStates(dom::ElementState::VISITED_OR_UNVISITED); 138 }