Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #include "XULElementAccessibles.h" |
michael@0 | 7 | |
michael@0 | 8 | #include "Accessible-inl.h" |
michael@0 | 9 | #include "BaseAccessibles.h" |
michael@0 | 10 | #include "DocAccessible-inl.h" |
michael@0 | 11 | #include "nsAccUtils.h" |
michael@0 | 12 | #include "nsCoreUtils.h" |
michael@0 | 13 | #include "nsTextEquivUtils.h" |
michael@0 | 14 | #include "Relation.h" |
michael@0 | 15 | #include "Role.h" |
michael@0 | 16 | #include "States.h" |
michael@0 | 17 | #include "TextUpdater.h" |
michael@0 | 18 | |
michael@0 | 19 | #ifdef A11Y_LOG |
michael@0 | 20 | #include "Logging.h" |
michael@0 | 21 | #endif |
michael@0 | 22 | |
michael@0 | 23 | #include "nsIAccessibleRelation.h" |
michael@0 | 24 | #include "nsIDOMXULDescriptionElement.h" |
michael@0 | 25 | #include "nsNameSpaceManager.h" |
michael@0 | 26 | #include "nsNetUtil.h" |
michael@0 | 27 | #include "nsString.h" |
michael@0 | 28 | #include "nsTextBoxFrame.h" |
michael@0 | 29 | |
michael@0 | 30 | using namespace mozilla::a11y; |
michael@0 | 31 | |
michael@0 | 32 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 33 | // XULLabelAccessible |
michael@0 | 34 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 35 | |
michael@0 | 36 | XULLabelAccessible:: |
michael@0 | 37 | XULLabelAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
michael@0 | 38 | HyperTextAccessibleWrap(aContent, aDoc) |
michael@0 | 39 | { |
michael@0 | 40 | mType = eXULLabelType; |
michael@0 | 41 | |
michael@0 | 42 | // If @value attribute is given then it's rendered instead text content. In |
michael@0 | 43 | // this case we need to create a text leaf accessible to make @value attribute |
michael@0 | 44 | // accessible. |
michael@0 | 45 | // XXX: text interface doesn't let you get the text by words. |
michael@0 | 46 | nsTextBoxFrame* textBoxFrame = do_QueryFrame(mContent->GetPrimaryFrame()); |
michael@0 | 47 | if (textBoxFrame) { |
michael@0 | 48 | mValueTextLeaf = new XULLabelTextLeafAccessible(mContent, mDoc); |
michael@0 | 49 | mDoc->BindToDocument(mValueTextLeaf, nullptr); |
michael@0 | 50 | |
michael@0 | 51 | nsAutoString text; |
michael@0 | 52 | textBoxFrame->GetCroppedTitle(text); |
michael@0 | 53 | mValueTextLeaf->SetText(text); |
michael@0 | 54 | } |
michael@0 | 55 | } |
michael@0 | 56 | |
michael@0 | 57 | void |
michael@0 | 58 | XULLabelAccessible::Shutdown() |
michael@0 | 59 | { |
michael@0 | 60 | mValueTextLeaf = nullptr; |
michael@0 | 61 | HyperTextAccessibleWrap::Shutdown(); |
michael@0 | 62 | } |
michael@0 | 63 | |
michael@0 | 64 | ENameValueFlag |
michael@0 | 65 | XULLabelAccessible::NativeName(nsString& aName) |
michael@0 | 66 | { |
michael@0 | 67 | // if the value attr doesn't exist, the screen reader must get the accessible text |
michael@0 | 68 | // from the accessible text interface or from the children |
michael@0 | 69 | if (mValueTextLeaf) |
michael@0 | 70 | return mValueTextLeaf->Name(aName); |
michael@0 | 71 | |
michael@0 | 72 | return eNameOK; |
michael@0 | 73 | } |
michael@0 | 74 | |
michael@0 | 75 | role |
michael@0 | 76 | XULLabelAccessible::NativeRole() |
michael@0 | 77 | { |
michael@0 | 78 | return roles::LABEL; |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | uint64_t |
michael@0 | 82 | XULLabelAccessible::NativeState() |
michael@0 | 83 | { |
michael@0 | 84 | // Labels and description have read only state |
michael@0 | 85 | // They are not focusable or selectable |
michael@0 | 86 | return HyperTextAccessibleWrap::NativeState() | states::READONLY; |
michael@0 | 87 | } |
michael@0 | 88 | |
michael@0 | 89 | Relation |
michael@0 | 90 | XULLabelAccessible::RelationByType(RelationType aType) |
michael@0 | 91 | { |
michael@0 | 92 | Relation rel = HyperTextAccessibleWrap::RelationByType(aType); |
michael@0 | 93 | if (aType == RelationType::LABEL_FOR) { |
michael@0 | 94 | // Caption is the label for groupbox |
michael@0 | 95 | nsIContent* parent = mContent->GetFlattenedTreeParent(); |
michael@0 | 96 | if (parent && parent->Tag() == nsGkAtoms::caption) { |
michael@0 | 97 | Accessible* parent = Parent(); |
michael@0 | 98 | if (parent && parent->Role() == roles::GROUPING) |
michael@0 | 99 | rel.AppendTarget(parent); |
michael@0 | 100 | } |
michael@0 | 101 | } |
michael@0 | 102 | |
michael@0 | 103 | return rel; |
michael@0 | 104 | } |
michael@0 | 105 | |
michael@0 | 106 | void |
michael@0 | 107 | XULLabelAccessible::UpdateLabelValue(const nsString& aValue) |
michael@0 | 108 | { |
michael@0 | 109 | #ifdef A11Y_LOG |
michael@0 | 110 | if (logging::IsEnabled(logging::eText)) { |
michael@0 | 111 | logging::MsgBegin("TEXT", "text may be changed (xul:label @value update)"); |
michael@0 | 112 | logging::Node("container", mContent); |
michael@0 | 113 | logging::MsgEntry("old text '%s'", |
michael@0 | 114 | NS_ConvertUTF16toUTF8(mValueTextLeaf->Text()).get()); |
michael@0 | 115 | logging::MsgEntry("new text: '%s'", |
michael@0 | 116 | NS_ConvertUTF16toUTF8(aValue).get()); |
michael@0 | 117 | logging::MsgEnd(); |
michael@0 | 118 | } |
michael@0 | 119 | #endif |
michael@0 | 120 | |
michael@0 | 121 | TextUpdater::Run(mDoc, mValueTextLeaf, aValue); |
michael@0 | 122 | } |
michael@0 | 123 | |
michael@0 | 124 | void |
michael@0 | 125 | XULLabelAccessible::CacheChildren() |
michael@0 | 126 | { |
michael@0 | 127 | if (mValueTextLeaf) { |
michael@0 | 128 | AppendChild(mValueTextLeaf); |
michael@0 | 129 | return; |
michael@0 | 130 | } |
michael@0 | 131 | |
michael@0 | 132 | // Cache children from subtree. |
michael@0 | 133 | AccessibleWrap::CacheChildren(); |
michael@0 | 134 | } |
michael@0 | 135 | |
michael@0 | 136 | |
michael@0 | 137 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 138 | // XULLabelTextLeafAccessible |
michael@0 | 139 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 140 | |
michael@0 | 141 | role |
michael@0 | 142 | XULLabelTextLeafAccessible::NativeRole() |
michael@0 | 143 | { |
michael@0 | 144 | return roles::TEXT_LEAF; |
michael@0 | 145 | } |
michael@0 | 146 | |
michael@0 | 147 | uint64_t |
michael@0 | 148 | XULLabelTextLeafAccessible::NativeState() |
michael@0 | 149 | { |
michael@0 | 150 | return TextLeafAccessibleWrap::NativeState() | states::READONLY; |
michael@0 | 151 | } |
michael@0 | 152 | |
michael@0 | 153 | |
michael@0 | 154 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 155 | // XULTooltipAccessible |
michael@0 | 156 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 157 | |
michael@0 | 158 | XULTooltipAccessible:: |
michael@0 | 159 | XULTooltipAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
michael@0 | 160 | LeafAccessible(aContent, aDoc) |
michael@0 | 161 | { |
michael@0 | 162 | } |
michael@0 | 163 | |
michael@0 | 164 | uint64_t |
michael@0 | 165 | XULTooltipAccessible::NativeState() |
michael@0 | 166 | { |
michael@0 | 167 | return LeafAccessible::NativeState() | states::READONLY; |
michael@0 | 168 | } |
michael@0 | 169 | |
michael@0 | 170 | role |
michael@0 | 171 | XULTooltipAccessible::NativeRole() |
michael@0 | 172 | { |
michael@0 | 173 | return roles::TOOLTIP; |
michael@0 | 174 | } |
michael@0 | 175 | |
michael@0 | 176 | |
michael@0 | 177 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 178 | // XULLinkAccessible |
michael@0 | 179 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 180 | |
michael@0 | 181 | XULLinkAccessible:: |
michael@0 | 182 | XULLinkAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
michael@0 | 183 | XULLabelAccessible(aContent, aDoc) |
michael@0 | 184 | { |
michael@0 | 185 | } |
michael@0 | 186 | |
michael@0 | 187 | // Expose nsIAccessibleHyperLink unconditionally |
michael@0 | 188 | NS_IMPL_ISUPPORTS_INHERITED(XULLinkAccessible, XULLabelAccessible, |
michael@0 | 189 | nsIAccessibleHyperLink) |
michael@0 | 190 | |
michael@0 | 191 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 192 | // XULLinkAccessible. nsIAccessible |
michael@0 | 193 | |
michael@0 | 194 | void |
michael@0 | 195 | XULLinkAccessible::Value(nsString& aValue) |
michael@0 | 196 | { |
michael@0 | 197 | aValue.Truncate(); |
michael@0 | 198 | |
michael@0 | 199 | mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, aValue); |
michael@0 | 200 | } |
michael@0 | 201 | |
michael@0 | 202 | ENameValueFlag |
michael@0 | 203 | XULLinkAccessible::NativeName(nsString& aName) |
michael@0 | 204 | { |
michael@0 | 205 | mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName); |
michael@0 | 206 | if (!aName.IsEmpty()) |
michael@0 | 207 | return eNameOK; |
michael@0 | 208 | |
michael@0 | 209 | nsTextEquivUtils::GetNameFromSubtree(this, aName); |
michael@0 | 210 | return aName.IsEmpty() ? eNameOK : eNameFromSubtree; |
michael@0 | 211 | } |
michael@0 | 212 | |
michael@0 | 213 | role |
michael@0 | 214 | XULLinkAccessible::NativeRole() |
michael@0 | 215 | { |
michael@0 | 216 | return roles::LINK; |
michael@0 | 217 | } |
michael@0 | 218 | |
michael@0 | 219 | |
michael@0 | 220 | uint64_t |
michael@0 | 221 | XULLinkAccessible::NativeLinkState() const |
michael@0 | 222 | { |
michael@0 | 223 | return states::LINKED; |
michael@0 | 224 | } |
michael@0 | 225 | |
michael@0 | 226 | uint8_t |
michael@0 | 227 | XULLinkAccessible::ActionCount() |
michael@0 | 228 | { |
michael@0 | 229 | return 1; |
michael@0 | 230 | } |
michael@0 | 231 | |
michael@0 | 232 | NS_IMETHODIMP |
michael@0 | 233 | XULLinkAccessible::GetActionName(uint8_t aIndex, nsAString& aName) |
michael@0 | 234 | { |
michael@0 | 235 | aName.Truncate(); |
michael@0 | 236 | |
michael@0 | 237 | if (aIndex != eAction_Jump) |
michael@0 | 238 | return NS_ERROR_INVALID_ARG; |
michael@0 | 239 | |
michael@0 | 240 | aName.AssignLiteral("jump"); |
michael@0 | 241 | return NS_OK; |
michael@0 | 242 | } |
michael@0 | 243 | |
michael@0 | 244 | NS_IMETHODIMP |
michael@0 | 245 | XULLinkAccessible::DoAction(uint8_t aIndex) |
michael@0 | 246 | { |
michael@0 | 247 | if (aIndex != eAction_Jump) |
michael@0 | 248 | return NS_ERROR_INVALID_ARG; |
michael@0 | 249 | |
michael@0 | 250 | if (IsDefunct()) |
michael@0 | 251 | return NS_ERROR_FAILURE; |
michael@0 | 252 | |
michael@0 | 253 | DoCommand(); |
michael@0 | 254 | return NS_OK; |
michael@0 | 255 | } |
michael@0 | 256 | |
michael@0 | 257 | //////////////////////////////////////////////////////////////////////////////// |
michael@0 | 258 | // XULLinkAccessible: HyperLinkAccessible |
michael@0 | 259 | |
michael@0 | 260 | bool |
michael@0 | 261 | XULLinkAccessible::IsLink() |
michael@0 | 262 | { |
michael@0 | 263 | // Expose HyperLinkAccessible unconditionally. |
michael@0 | 264 | return true; |
michael@0 | 265 | } |
michael@0 | 266 | |
michael@0 | 267 | uint32_t |
michael@0 | 268 | XULLinkAccessible::StartOffset() |
michael@0 | 269 | { |
michael@0 | 270 | // If XUL link accessible is not contained by hypertext accessible then |
michael@0 | 271 | // start offset matches index in parent because the parent doesn't contains |
michael@0 | 272 | // a text. |
michael@0 | 273 | // XXX: accessible parent of XUL link accessible should be a hypertext |
michael@0 | 274 | // accessible. |
michael@0 | 275 | if (Accessible::IsLink()) |
michael@0 | 276 | return Accessible::StartOffset(); |
michael@0 | 277 | return IndexInParent(); |
michael@0 | 278 | } |
michael@0 | 279 | |
michael@0 | 280 | uint32_t |
michael@0 | 281 | XULLinkAccessible::EndOffset() |
michael@0 | 282 | { |
michael@0 | 283 | if (Accessible::IsLink()) |
michael@0 | 284 | return Accessible::EndOffset(); |
michael@0 | 285 | return IndexInParent() + 1; |
michael@0 | 286 | } |
michael@0 | 287 | |
michael@0 | 288 | already_AddRefed<nsIURI> |
michael@0 | 289 | XULLinkAccessible::AnchorURIAt(uint32_t aAnchorIndex) |
michael@0 | 290 | { |
michael@0 | 291 | if (aAnchorIndex != 0) |
michael@0 | 292 | return nullptr; |
michael@0 | 293 | |
michael@0 | 294 | nsAutoString href; |
michael@0 | 295 | mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href); |
michael@0 | 296 | |
michael@0 | 297 | nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI(); |
michael@0 | 298 | nsIDocument* document = mContent->OwnerDoc(); |
michael@0 | 299 | |
michael@0 | 300 | nsCOMPtr<nsIURI> anchorURI; |
michael@0 | 301 | NS_NewURI(getter_AddRefs(anchorURI), href, |
michael@0 | 302 | document->GetDocumentCharacterSet().get(), |
michael@0 | 303 | baseURI); |
michael@0 | 304 | |
michael@0 | 305 | return anchorURI.forget(); |
michael@0 | 306 | } |