1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/xul/XULElementAccessibles.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,306 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "XULElementAccessibles.h" 1.10 + 1.11 +#include "Accessible-inl.h" 1.12 +#include "BaseAccessibles.h" 1.13 +#include "DocAccessible-inl.h" 1.14 +#include "nsAccUtils.h" 1.15 +#include "nsCoreUtils.h" 1.16 +#include "nsTextEquivUtils.h" 1.17 +#include "Relation.h" 1.18 +#include "Role.h" 1.19 +#include "States.h" 1.20 +#include "TextUpdater.h" 1.21 + 1.22 +#ifdef A11Y_LOG 1.23 +#include "Logging.h" 1.24 +#endif 1.25 + 1.26 +#include "nsIAccessibleRelation.h" 1.27 +#include "nsIDOMXULDescriptionElement.h" 1.28 +#include "nsNameSpaceManager.h" 1.29 +#include "nsNetUtil.h" 1.30 +#include "nsString.h" 1.31 +#include "nsTextBoxFrame.h" 1.32 + 1.33 +using namespace mozilla::a11y; 1.34 + 1.35 +//////////////////////////////////////////////////////////////////////////////// 1.36 +// XULLabelAccessible 1.37 +//////////////////////////////////////////////////////////////////////////////// 1.38 + 1.39 +XULLabelAccessible:: 1.40 + XULLabelAccessible(nsIContent* aContent, DocAccessible* aDoc) : 1.41 + HyperTextAccessibleWrap(aContent, aDoc) 1.42 +{ 1.43 + mType = eXULLabelType; 1.44 + 1.45 + // If @value attribute is given then it's rendered instead text content. In 1.46 + // this case we need to create a text leaf accessible to make @value attribute 1.47 + // accessible. 1.48 + // XXX: text interface doesn't let you get the text by words. 1.49 + nsTextBoxFrame* textBoxFrame = do_QueryFrame(mContent->GetPrimaryFrame()); 1.50 + if (textBoxFrame) { 1.51 + mValueTextLeaf = new XULLabelTextLeafAccessible(mContent, mDoc); 1.52 + mDoc->BindToDocument(mValueTextLeaf, nullptr); 1.53 + 1.54 + nsAutoString text; 1.55 + textBoxFrame->GetCroppedTitle(text); 1.56 + mValueTextLeaf->SetText(text); 1.57 + } 1.58 +} 1.59 + 1.60 +void 1.61 +XULLabelAccessible::Shutdown() 1.62 +{ 1.63 + mValueTextLeaf = nullptr; 1.64 + HyperTextAccessibleWrap::Shutdown(); 1.65 +} 1.66 + 1.67 +ENameValueFlag 1.68 +XULLabelAccessible::NativeName(nsString& aName) 1.69 +{ 1.70 + // if the value attr doesn't exist, the screen reader must get the accessible text 1.71 + // from the accessible text interface or from the children 1.72 + if (mValueTextLeaf) 1.73 + return mValueTextLeaf->Name(aName); 1.74 + 1.75 + return eNameOK; 1.76 +} 1.77 + 1.78 +role 1.79 +XULLabelAccessible::NativeRole() 1.80 +{ 1.81 + return roles::LABEL; 1.82 +} 1.83 + 1.84 +uint64_t 1.85 +XULLabelAccessible::NativeState() 1.86 +{ 1.87 + // Labels and description have read only state 1.88 + // They are not focusable or selectable 1.89 + return HyperTextAccessibleWrap::NativeState() | states::READONLY; 1.90 +} 1.91 + 1.92 +Relation 1.93 +XULLabelAccessible::RelationByType(RelationType aType) 1.94 +{ 1.95 + Relation rel = HyperTextAccessibleWrap::RelationByType(aType); 1.96 + if (aType == RelationType::LABEL_FOR) { 1.97 + // Caption is the label for groupbox 1.98 + nsIContent* parent = mContent->GetFlattenedTreeParent(); 1.99 + if (parent && parent->Tag() == nsGkAtoms::caption) { 1.100 + Accessible* parent = Parent(); 1.101 + if (parent && parent->Role() == roles::GROUPING) 1.102 + rel.AppendTarget(parent); 1.103 + } 1.104 + } 1.105 + 1.106 + return rel; 1.107 +} 1.108 + 1.109 +void 1.110 +XULLabelAccessible::UpdateLabelValue(const nsString& aValue) 1.111 +{ 1.112 +#ifdef A11Y_LOG 1.113 + if (logging::IsEnabled(logging::eText)) { 1.114 + logging::MsgBegin("TEXT", "text may be changed (xul:label @value update)"); 1.115 + logging::Node("container", mContent); 1.116 + logging::MsgEntry("old text '%s'", 1.117 + NS_ConvertUTF16toUTF8(mValueTextLeaf->Text()).get()); 1.118 + logging::MsgEntry("new text: '%s'", 1.119 + NS_ConvertUTF16toUTF8(aValue).get()); 1.120 + logging::MsgEnd(); 1.121 + } 1.122 +#endif 1.123 + 1.124 + TextUpdater::Run(mDoc, mValueTextLeaf, aValue); 1.125 +} 1.126 + 1.127 +void 1.128 +XULLabelAccessible::CacheChildren() 1.129 +{ 1.130 + if (mValueTextLeaf) { 1.131 + AppendChild(mValueTextLeaf); 1.132 + return; 1.133 + } 1.134 + 1.135 + // Cache children from subtree. 1.136 + AccessibleWrap::CacheChildren(); 1.137 +} 1.138 + 1.139 + 1.140 +//////////////////////////////////////////////////////////////////////////////// 1.141 +// XULLabelTextLeafAccessible 1.142 +//////////////////////////////////////////////////////////////////////////////// 1.143 + 1.144 +role 1.145 +XULLabelTextLeafAccessible::NativeRole() 1.146 +{ 1.147 + return roles::TEXT_LEAF; 1.148 +} 1.149 + 1.150 +uint64_t 1.151 +XULLabelTextLeafAccessible::NativeState() 1.152 +{ 1.153 + return TextLeafAccessibleWrap::NativeState() | states::READONLY; 1.154 +} 1.155 + 1.156 + 1.157 +//////////////////////////////////////////////////////////////////////////////// 1.158 +// XULTooltipAccessible 1.159 +//////////////////////////////////////////////////////////////////////////////// 1.160 + 1.161 +XULTooltipAccessible:: 1.162 + XULTooltipAccessible(nsIContent* aContent, DocAccessible* aDoc) : 1.163 + LeafAccessible(aContent, aDoc) 1.164 +{ 1.165 +} 1.166 + 1.167 +uint64_t 1.168 +XULTooltipAccessible::NativeState() 1.169 +{ 1.170 + return LeafAccessible::NativeState() | states::READONLY; 1.171 +} 1.172 + 1.173 +role 1.174 +XULTooltipAccessible::NativeRole() 1.175 +{ 1.176 + return roles::TOOLTIP; 1.177 +} 1.178 + 1.179 + 1.180 +//////////////////////////////////////////////////////////////////////////////// 1.181 +// XULLinkAccessible 1.182 +//////////////////////////////////////////////////////////////////////////////// 1.183 + 1.184 +XULLinkAccessible:: 1.185 + XULLinkAccessible(nsIContent* aContent, DocAccessible* aDoc) : 1.186 + XULLabelAccessible(aContent, aDoc) 1.187 +{ 1.188 +} 1.189 + 1.190 +// Expose nsIAccessibleHyperLink unconditionally 1.191 +NS_IMPL_ISUPPORTS_INHERITED(XULLinkAccessible, XULLabelAccessible, 1.192 + nsIAccessibleHyperLink) 1.193 + 1.194 +//////////////////////////////////////////////////////////////////////////////// 1.195 +// XULLinkAccessible. nsIAccessible 1.196 + 1.197 +void 1.198 +XULLinkAccessible::Value(nsString& aValue) 1.199 +{ 1.200 + aValue.Truncate(); 1.201 + 1.202 + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, aValue); 1.203 +} 1.204 + 1.205 +ENameValueFlag 1.206 +XULLinkAccessible::NativeName(nsString& aName) 1.207 +{ 1.208 + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName); 1.209 + if (!aName.IsEmpty()) 1.210 + return eNameOK; 1.211 + 1.212 + nsTextEquivUtils::GetNameFromSubtree(this, aName); 1.213 + return aName.IsEmpty() ? eNameOK : eNameFromSubtree; 1.214 +} 1.215 + 1.216 +role 1.217 +XULLinkAccessible::NativeRole() 1.218 +{ 1.219 + return roles::LINK; 1.220 +} 1.221 + 1.222 + 1.223 +uint64_t 1.224 +XULLinkAccessible::NativeLinkState() const 1.225 +{ 1.226 + return states::LINKED; 1.227 +} 1.228 + 1.229 +uint8_t 1.230 +XULLinkAccessible::ActionCount() 1.231 +{ 1.232 + return 1; 1.233 +} 1.234 + 1.235 +NS_IMETHODIMP 1.236 +XULLinkAccessible::GetActionName(uint8_t aIndex, nsAString& aName) 1.237 +{ 1.238 + aName.Truncate(); 1.239 + 1.240 + if (aIndex != eAction_Jump) 1.241 + return NS_ERROR_INVALID_ARG; 1.242 + 1.243 + aName.AssignLiteral("jump"); 1.244 + return NS_OK; 1.245 +} 1.246 + 1.247 +NS_IMETHODIMP 1.248 +XULLinkAccessible::DoAction(uint8_t aIndex) 1.249 +{ 1.250 + if (aIndex != eAction_Jump) 1.251 + return NS_ERROR_INVALID_ARG; 1.252 + 1.253 + if (IsDefunct()) 1.254 + return NS_ERROR_FAILURE; 1.255 + 1.256 + DoCommand(); 1.257 + return NS_OK; 1.258 +} 1.259 + 1.260 +//////////////////////////////////////////////////////////////////////////////// 1.261 +// XULLinkAccessible: HyperLinkAccessible 1.262 + 1.263 +bool 1.264 +XULLinkAccessible::IsLink() 1.265 +{ 1.266 + // Expose HyperLinkAccessible unconditionally. 1.267 + return true; 1.268 +} 1.269 + 1.270 +uint32_t 1.271 +XULLinkAccessible::StartOffset() 1.272 +{ 1.273 + // If XUL link accessible is not contained by hypertext accessible then 1.274 + // start offset matches index in parent because the parent doesn't contains 1.275 + // a text. 1.276 + // XXX: accessible parent of XUL link accessible should be a hypertext 1.277 + // accessible. 1.278 + if (Accessible::IsLink()) 1.279 + return Accessible::StartOffset(); 1.280 + return IndexInParent(); 1.281 +} 1.282 + 1.283 +uint32_t 1.284 +XULLinkAccessible::EndOffset() 1.285 +{ 1.286 + if (Accessible::IsLink()) 1.287 + return Accessible::EndOffset(); 1.288 + return IndexInParent() + 1; 1.289 +} 1.290 + 1.291 +already_AddRefed<nsIURI> 1.292 +XULLinkAccessible::AnchorURIAt(uint32_t aAnchorIndex) 1.293 +{ 1.294 + if (aAnchorIndex != 0) 1.295 + return nullptr; 1.296 + 1.297 + nsAutoString href; 1.298 + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href); 1.299 + 1.300 + nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI(); 1.301 + nsIDocument* document = mContent->OwnerDoc(); 1.302 + 1.303 + nsCOMPtr<nsIURI> anchorURI; 1.304 + NS_NewURI(getter_AddRefs(anchorURI), href, 1.305 + document->GetDocumentCharacterSet().get(), 1.306 + baseURI); 1.307 + 1.308 + return anchorURI.forget(); 1.309 +}