XULElementAccessibles.cpp (6667B)
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 "XULElementAccessibles.h" 7 8 #include "LocalAccessible-inl.h" 9 #include "BaseAccessibles.h" 10 #include "DocAccessible-inl.h" 11 #include "nsAccUtils.h" 12 #include "nsCoreUtils.h" 13 #include "nsTextEquivUtils.h" 14 #include "Relation.h" 15 #include "mozilla/a11y/Role.h" 16 #include "States.h" 17 #include "TextUpdater.h" 18 19 #ifdef A11Y_LOG 20 # include "Logging.h" 21 #endif 22 23 #include "nsNameSpaceManager.h" 24 #include "nsNetUtil.h" 25 #include "nsString.h" 26 #include "nsXULElement.h" 27 28 using namespace mozilla::a11y; 29 30 //////////////////////////////////////////////////////////////////////////////// 31 // XULLabelAccessible 32 //////////////////////////////////////////////////////////////////////////////// 33 34 XULLabelAccessible::XULLabelAccessible(nsIContent* aContent, 35 DocAccessible* aDoc) 36 : HyperTextAccessible(aContent, aDoc) { 37 mType = eXULLabelType; 38 } 39 40 void XULLabelAccessible::Shutdown() { 41 mValueTextLeaf = nullptr; 42 HyperTextAccessible::Shutdown(); 43 } 44 45 void XULLabelAccessible::DispatchClickEvent(uint32_t aActionIndex) const { 46 // Bug 1578140: For labels inside buttons, The base implementation of 47 // DispatchClickEvent doesn't fire a command event on the button. 48 RefPtr<nsXULElement> el = nsXULElement::FromNodeOrNull(mContent); 49 if (el) { 50 el->Click(mozilla::dom::CallerType::System); 51 } 52 } 53 54 ENameValueFlag XULLabelAccessible::NativeName(nsString& aName) const { 55 // if the value attr doesn't exist, the screen reader must get the accessible 56 // text from the accessible text interface or from the children 57 if (mValueTextLeaf) return mValueTextLeaf->Name(aName); 58 59 return LocalAccessible::NativeName(aName); 60 } 61 62 role XULLabelAccessible::NativeRole() const { return roles::LABEL; } 63 64 uint64_t XULLabelAccessible::NativeState() const { 65 // Labels and description have read only state 66 // They are not focusable or selectable 67 return HyperTextAccessible::NativeState() | states::READONLY; 68 } 69 70 Relation XULLabelAccessible::RelationByType(RelationType aType) const { 71 Relation rel = HyperTextAccessible::RelationByType(aType); 72 73 // The label for xul:groupbox is generated from the first xul:label 74 if (aType == RelationType::LABEL_FOR) { 75 LocalAccessible* parent = LocalParent(); 76 if (parent && parent->Role() == roles::GROUPING && 77 parent->LocalChildAt(0) == this) { 78 nsIContent* parentContent = parent->GetContent(); 79 if (parentContent && parentContent->IsXULElement(nsGkAtoms::groupbox)) { 80 rel.AppendTarget(parent); 81 } 82 } 83 } 84 85 return rel; 86 } 87 88 void XULLabelAccessible::UpdateLabelValue(const nsString& aValue) { 89 #ifdef A11Y_LOG 90 if (logging::IsEnabled(logging::eText)) { 91 logging::MsgBegin("TEXT", "text may be changed (xul:label @value update)"); 92 logging::Node("container", mContent); 93 logging::MsgEntry("old text '%s'", 94 NS_ConvertUTF16toUTF8(mValueTextLeaf->Text()).get()); 95 logging::MsgEntry("new text: '%s'", NS_ConvertUTF16toUTF8(aValue).get()); 96 logging::MsgEnd(); 97 } 98 #endif 99 100 TextUpdater::Run(mDoc, mValueTextLeaf, aValue); 101 } 102 103 //////////////////////////////////////////////////////////////////////////////// 104 // XULLabelTextLeafAccessible 105 //////////////////////////////////////////////////////////////////////////////// 106 107 role XULLabelTextLeafAccessible::NativeRole() const { return roles::TEXT_LEAF; } 108 109 uint64_t XULLabelTextLeafAccessible::NativeState() const { 110 return TextLeafAccessible::NativeState() | states::READONLY; 111 } 112 113 //////////////////////////////////////////////////////////////////////////////// 114 // XULTooltipAccessible 115 //////////////////////////////////////////////////////////////////////////////// 116 117 XULTooltipAccessible::XULTooltipAccessible(nsIContent* aContent, 118 DocAccessible* aDoc) 119 : LeafAccessible(aContent, aDoc) { 120 mType = eXULTooltipType; 121 } 122 123 uint64_t XULTooltipAccessible::NativeState() const { 124 return LeafAccessible::NativeState() | states::READONLY; 125 } 126 127 role XULTooltipAccessible::NativeRole() const { return roles::TOOLTIP; } 128 129 //////////////////////////////////////////////////////////////////////////////// 130 // XULLinkAccessible 131 //////////////////////////////////////////////////////////////////////////////// 132 133 XULLinkAccessible::XULLinkAccessible(nsIContent* aContent, DocAccessible* aDoc) 134 : XULLabelAccessible(aContent, aDoc) {} 135 136 XULLinkAccessible::~XULLinkAccessible() {} 137 138 //////////////////////////////////////////////////////////////////////////////// 139 // XULLinkAccessible: LocalAccessible 140 141 void XULLinkAccessible::Value(nsString& aValue) const { 142 aValue.Truncate(); 143 144 mContent->AsElement()->GetAttr(nsGkAtoms::href, aValue); 145 } 146 147 ENameValueFlag XULLinkAccessible::NativeName(nsString& aName) const { 148 mContent->AsElement()->GetAttr(nsGkAtoms::value, aName); 149 return eNameOK; 150 } 151 152 role XULLinkAccessible::NativeRole() const { return roles::LINK; } 153 154 uint64_t XULLinkAccessible::NativeLinkState() const { return states::LINKED; } 155 156 bool XULLinkAccessible::HasPrimaryAction() const { return true; } 157 158 void XULLinkAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) { 159 aName.Truncate(); 160 161 if (aIndex == eAction_Jump) aName.AssignLiteral("jump"); 162 } 163 164 //////////////////////////////////////////////////////////////////////////////// 165 // XULLinkAccessible: HyperLinkAccessible 166 167 bool XULLinkAccessible::IsLink() const { 168 // Expose HyperLinkAccessible unconditionally. 169 return true; 170 } 171 172 uint32_t XULLinkAccessible::StartOffset() { 173 // If XUL link accessible is not contained by hypertext accessible then 174 // start offset matches index in parent because the parent doesn't contains 175 // a text. 176 // XXX: accessible parent of XUL link accessible should be a hypertext 177 // accessible. 178 if (LocalAccessible::IsLink()) return LocalAccessible::StartOffset(); 179 return IndexInParent(); 180 } 181 182 uint32_t XULLinkAccessible::EndOffset() { 183 if (LocalAccessible::IsLink()) return LocalAccessible::EndOffset(); 184 return IndexInParent() + 1; 185 } 186 187 already_AddRefed<nsIURI> XULLinkAccessible::AnchorURIAt( 188 uint32_t aAnchorIndex) const { 189 if (aAnchorIndex != 0) return nullptr; 190 191 nsAutoString href; 192 mContent->AsElement()->GetAttr(nsGkAtoms::href, href); 193 194 dom::Document* document = mContent->OwnerDoc(); 195 196 nsCOMPtr<nsIURI> anchorURI; 197 NS_NewURI(getter_AddRefs(anchorURI), href, 198 document->GetDocumentCharacterSet(), mContent->GetBaseURI()); 199 200 return anchorURI.forget(); 201 }