1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/windows/sdn/sdnAccessible.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,535 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "sdnAccessible-inl.h" 1.11 +#include "ISimpleDOMNode_i.c" 1.12 + 1.13 +#include "DocAccessibleWrap.h" 1.14 + 1.15 +#include "nsAttrName.h" 1.16 +#include "nsCoreUtils.h" 1.17 +#include "nsIAccessibleTypes.h" 1.18 +#include "nsIDOMHTMLElement.h" 1.19 +#include "nsIDOMCSSStyleDeclaration.h" 1.20 +#include "nsNameSpaceManager.h" 1.21 +#include "nsServiceManagerUtils.h" 1.22 +#include "nsWinUtils.h" 1.23 + 1.24 +#include "nsAutoPtr.h" 1.25 + 1.26 +#include "mozilla/dom/Element.h" 1.27 + 1.28 +using namespace mozilla; 1.29 +using namespace mozilla::a11y; 1.30 + 1.31 +STDMETHODIMP 1.32 +sdnAccessible::QueryInterface(REFIID aREFIID, void** aInstancePtr) 1.33 +{ 1.34 + A11Y_TRYBLOCK_BEGIN 1.35 + 1.36 + if (!aInstancePtr) 1.37 + return E_FAIL; 1.38 + *aInstancePtr = nullptr; 1.39 + 1.40 + if (aREFIID == IID_ISimpleDOMNode) { 1.41 + *aInstancePtr = static_cast<ISimpleDOMNode*>(this); 1.42 + AddRef(); 1.43 + return S_OK; 1.44 + } 1.45 + 1.46 + AccessibleWrap* accessible = static_cast<AccessibleWrap*>(GetAccessible()); 1.47 + if (accessible) 1.48 + return accessible->QueryInterface(aREFIID, aInstancePtr); 1.49 + 1.50 + // IUnknown* is the canonical one if and only if this accessible doesn't have 1.51 + // an accessible. 1.52 + if (aREFIID == IID_IUnknown) { 1.53 + *aInstancePtr = static_cast<ISimpleDOMNode*>(this); 1.54 + AddRef(); 1.55 + return S_OK; 1.56 + } 1.57 + 1.58 + return E_NOINTERFACE; 1.59 + 1.60 + A11Y_TRYBLOCK_END 1.61 +} 1.62 + 1.63 +STDMETHODIMP 1.64 +sdnAccessible::get_nodeInfo(BSTR __RPC_FAR* aNodeName, 1.65 + short __RPC_FAR* aNameSpaceID, 1.66 + BSTR __RPC_FAR* aNodeValue, 1.67 + unsigned int __RPC_FAR* aNumChildren, 1.68 + unsigned int __RPC_FAR* aUniqueID, 1.69 + unsigned short __RPC_FAR* aNodeType) 1.70 +{ 1.71 + A11Y_TRYBLOCK_BEGIN 1.72 + 1.73 + if (!aNodeName || !aNameSpaceID || !aNodeValue || !aNumChildren || 1.74 + !aUniqueID || !aNodeType) 1.75 + return E_INVALIDARG; 1.76 + 1.77 + *aNodeName = nullptr; 1.78 + *aNameSpaceID = 0; 1.79 + *aNodeValue = nullptr; 1.80 + *aNumChildren = 0; 1.81 + *aUniqueID = 0; 1.82 + *aNodeType = 0; 1.83 + 1.84 + if (IsDefunct()) 1.85 + return CO_E_OBJNOTCONNECTED; 1.86 + 1.87 + nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(mNode)); 1.88 + 1.89 + uint16_t nodeType = 0; 1.90 + DOMNode->GetNodeType(&nodeType); 1.91 + *aNodeType = static_cast<unsigned short>(nodeType); 1.92 + 1.93 + if (*aNodeType != NODETYPE_TEXT) { 1.94 + nsAutoString nodeName; 1.95 + DOMNode->GetNodeName(nodeName); 1.96 + *aNodeName = ::SysAllocString(nodeName.get()); 1.97 + } 1.98 + 1.99 + nsAutoString nodeValue; 1.100 + DOMNode->GetNodeValue(nodeValue); 1.101 + *aNodeValue = ::SysAllocString(nodeValue.get()); 1.102 + 1.103 + *aNameSpaceID = mNode->IsNodeOfType(nsINode::eCONTENT) ? 1.104 + static_cast<short>(mNode->AsContent()->GetNameSpaceID()) : 0; 1.105 + 1.106 + // This is a unique ID for every content node. The 3rd party accessibility 1.107 + // application can compare this to the childID we return for events such as 1.108 + // focus events, to correlate back to data nodes in their internal object 1.109 + // model. 1.110 + Accessible* accessible = GetAccessible(); 1.111 + *aUniqueID = - NS_PTR_TO_INT32(accessible ? accessible->UniqueID() : 1.112 + static_cast<void*>(this)); 1.113 + 1.114 + *aNumChildren = mNode->GetChildCount(); 1.115 + 1.116 + return S_OK; 1.117 + 1.118 + A11Y_TRYBLOCK_END 1.119 +} 1.120 + 1.121 +STDMETHODIMP 1.122 +sdnAccessible::get_attributes(unsigned short aMaxAttribs, 1.123 + BSTR __RPC_FAR* aAttribNames, 1.124 + short __RPC_FAR* aNameSpaceIDs, 1.125 + BSTR __RPC_FAR* aAttribValues, 1.126 + unsigned short __RPC_FAR* aNumAttribs) 1.127 +{ 1.128 + A11Y_TRYBLOCK_BEGIN 1.129 + 1.130 + if (!aAttribNames || !aNameSpaceIDs || !aAttribValues || !aNumAttribs) 1.131 + return E_INVALIDARG; 1.132 + 1.133 + *aNumAttribs = 0; 1.134 + 1.135 + if (IsDefunct()) 1.136 + return CO_E_OBJNOTCONNECTED; 1.137 + 1.138 + if (!mNode->IsElement()) 1.139 + return S_FALSE; 1.140 + 1.141 + dom::Element* elm = mNode->AsElement(); 1.142 + uint32_t numAttribs = elm->GetAttrCount(); 1.143 + if (numAttribs > aMaxAttribs) 1.144 + numAttribs = aMaxAttribs; 1.145 + 1.146 + *aNumAttribs = static_cast<unsigned short>(numAttribs); 1.147 + 1.148 + for (uint32_t index = 0; index < numAttribs; index++) { 1.149 + aNameSpaceIDs[index] = 0; 1.150 + aAttribValues[index] = aAttribNames[index] = nullptr; 1.151 + nsAutoString attributeValue; 1.152 + 1.153 + const nsAttrName* name = elm->GetAttrNameAt(index); 1.154 + aNameSpaceIDs[index] = static_cast<short>(name->NamespaceID()); 1.155 + aAttribNames[index] = ::SysAllocString(name->LocalName()->GetUTF16String()); 1.156 + elm->GetAttr(name->NamespaceID(), name->LocalName(), attributeValue); 1.157 + aAttribValues[index] = ::SysAllocString(attributeValue.get()); 1.158 + } 1.159 + 1.160 + return S_OK; 1.161 + 1.162 + A11Y_TRYBLOCK_END 1.163 +} 1.164 + 1.165 +STDMETHODIMP 1.166 +sdnAccessible::get_attributesForNames(unsigned short aMaxAttribs, 1.167 + BSTR __RPC_FAR* aAttribNames, 1.168 + short __RPC_FAR* aNameSpaceID, 1.169 + BSTR __RPC_FAR* aAttribValues) 1.170 +{ 1.171 + A11Y_TRYBLOCK_BEGIN 1.172 + 1.173 + if (!aAttribNames || !aNameSpaceID || !aAttribValues) 1.174 + return E_INVALIDARG; 1.175 + 1.176 + if (IsDefunct()) 1.177 + return CO_E_OBJNOTCONNECTED; 1.178 + 1.179 + if (!mNode->IsElement()) 1.180 + return S_FALSE; 1.181 + 1.182 + nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mNode)); 1.183 + nsNameSpaceManager* nameSpaceManager = nsNameSpaceManager::GetInstance(); 1.184 + 1.185 + int32_t index = 0; 1.186 + for (index = 0; index < aMaxAttribs; index++) { 1.187 + aAttribValues[index] = nullptr; 1.188 + if (aAttribNames[index]) { 1.189 + nsAutoString attributeValue, nameSpaceURI; 1.190 + nsAutoString attributeName(nsDependentString( 1.191 + static_cast<const wchar_t*>(aAttribNames[index]))); 1.192 + 1.193 + nsresult rv = NS_OK; 1.194 + if (aNameSpaceID[index]>0 && 1.195 + NS_SUCCEEDED(nameSpaceManager->GetNameSpaceURI(aNameSpaceID[index], 1.196 + nameSpaceURI))) { 1.197 + rv = domElement->GetAttributeNS(nameSpaceURI, attributeName, 1.198 + attributeValue); 1.199 + } else { 1.200 + rv = domElement->GetAttribute(attributeName, attributeValue); 1.201 + } 1.202 + 1.203 + if (NS_SUCCEEDED(rv)) 1.204 + aAttribValues[index] = ::SysAllocString(attributeValue.get()); 1.205 + } 1.206 + } 1.207 + 1.208 + return S_OK; 1.209 + 1.210 + A11Y_TRYBLOCK_END 1.211 +} 1.212 + 1.213 +STDMETHODIMP 1.214 +sdnAccessible::get_computedStyle(unsigned short aMaxStyleProperties, 1.215 + boolean aUseAlternateView, 1.216 + BSTR __RPC_FAR* aStyleProperties, 1.217 + BSTR __RPC_FAR* aStyleValues, 1.218 + unsigned short __RPC_FAR* aNumStyleProperties) 1.219 +{ 1.220 + A11Y_TRYBLOCK_BEGIN 1.221 + 1.222 + if (!aStyleProperties || aStyleValues || !aNumStyleProperties) 1.223 + return E_INVALIDARG; 1.224 + 1.225 + if (IsDefunct()) 1.226 + return CO_E_OBJNOTCONNECTED; 1.227 + 1.228 + *aNumStyleProperties = 0; 1.229 + 1.230 + if (mNode->IsNodeOfType(nsINode::eDOCUMENT)) 1.231 + return S_FALSE; 1.232 + 1.233 + nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl = 1.234 + nsWinUtils::GetComputedStyleDeclaration(mNode->AsContent()); 1.235 + NS_ENSURE_TRUE(cssDecl, E_FAIL); 1.236 + 1.237 + uint32_t length = 0; 1.238 + cssDecl->GetLength(&length); 1.239 + 1.240 + uint32_t index = 0, realIndex = 0; 1.241 + for (index = realIndex = 0; index < length && realIndex < aMaxStyleProperties; 1.242 + index ++) { 1.243 + nsAutoString property, value; 1.244 + 1.245 + // Ignore -moz-* properties. 1.246 + if (NS_SUCCEEDED(cssDecl->Item(index, property)) && property.CharAt(0) != '-') 1.247 + cssDecl->GetPropertyValue(property, value); // Get property value 1.248 + 1.249 + if (!value.IsEmpty()) { 1.250 + aStyleProperties[realIndex] = ::SysAllocString(property.get()); 1.251 + aStyleValues[realIndex] = ::SysAllocString(value.get()); 1.252 + ++realIndex; 1.253 + } 1.254 + } 1.255 + 1.256 + *aNumStyleProperties = static_cast<unsigned short>(realIndex); 1.257 + 1.258 + return S_OK; 1.259 + 1.260 + A11Y_TRYBLOCK_END 1.261 +} 1.262 + 1.263 +STDMETHODIMP 1.264 +sdnAccessible::get_computedStyleForProperties(unsigned short aNumStyleProperties, 1.265 + boolean aUseAlternateView, 1.266 + BSTR __RPC_FAR* aStyleProperties, 1.267 + BSTR __RPC_FAR* aStyleValues) 1.268 +{ 1.269 + A11Y_TRYBLOCK_BEGIN 1.270 + 1.271 + if (!aStyleProperties || !aStyleValues) 1.272 + return E_INVALIDARG; 1.273 + 1.274 + if (IsDefunct()) 1.275 + return CO_E_OBJNOTCONNECTED; 1.276 + 1.277 + if (mNode->IsNodeOfType(nsINode::eDOCUMENT)) 1.278 + return S_FALSE; 1.279 + 1.280 + nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl = 1.281 + nsWinUtils::GetComputedStyleDeclaration(mNode->AsContent()); 1.282 + NS_ENSURE_TRUE(cssDecl, E_FAIL); 1.283 + 1.284 + uint32_t index = 0; 1.285 + for (index = 0; index < aNumStyleProperties; index++) { 1.286 + nsAutoString value; 1.287 + if (aStyleProperties[index]) 1.288 + cssDecl->GetPropertyValue(nsDependentString(aStyleProperties[index]), value); // Get property value 1.289 + aStyleValues[index] = ::SysAllocString(value.get()); 1.290 + } 1.291 + 1.292 + return S_OK; 1.293 + 1.294 + A11Y_TRYBLOCK_END 1.295 +} 1.296 + 1.297 +STDMETHODIMP 1.298 +sdnAccessible::scrollTo(boolean aScrollTopLeft) 1.299 +{ 1.300 + A11Y_TRYBLOCK_BEGIN 1.301 + 1.302 + DocAccessible* document = GetDocument(); 1.303 + if (!document) // that's IsDefunct check 1.304 + return CO_E_OBJNOTCONNECTED; 1.305 + 1.306 + if (!mNode->IsContent()) 1.307 + return S_FALSE; 1.308 + 1.309 + uint32_t scrollType = 1.310 + aScrollTopLeft ? nsIAccessibleScrollType::SCROLL_TYPE_TOP_LEFT : 1.311 + nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_RIGHT; 1.312 + 1.313 + nsCoreUtils::ScrollTo(document->PresShell(), mNode->AsContent(), scrollType); 1.314 + return S_OK; 1.315 + 1.316 + A11Y_TRYBLOCK_END 1.317 +} 1.318 + 1.319 +STDMETHODIMP 1.320 +sdnAccessible::get_parentNode(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode) 1.321 +{ 1.322 + A11Y_TRYBLOCK_BEGIN 1.323 + 1.324 + if (!aNode) 1.325 + return E_INVALIDARG; 1.326 + *aNode = nullptr; 1.327 + 1.328 + if (IsDefunct()) 1.329 + return CO_E_OBJNOTCONNECTED; 1.330 + 1.331 + nsINode* resultNode = mNode->GetParentNode(); 1.332 + if (resultNode) { 1.333 + *aNode = static_cast<ISimpleDOMNode*>(new sdnAccessible(resultNode)); 1.334 + (*aNode)->AddRef(); 1.335 + } 1.336 + 1.337 + return S_OK; 1.338 + 1.339 + A11Y_TRYBLOCK_END 1.340 +} 1.341 + 1.342 +STDMETHODIMP 1.343 +sdnAccessible::get_firstChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode) 1.344 +{ 1.345 + A11Y_TRYBLOCK_BEGIN 1.346 + 1.347 + if (!aNode) 1.348 + return E_INVALIDARG; 1.349 + *aNode = nullptr; 1.350 + 1.351 + if (IsDefunct()) 1.352 + return CO_E_OBJNOTCONNECTED; 1.353 + 1.354 + nsINode* resultNode = mNode->GetFirstChild(); 1.355 + if (resultNode) { 1.356 + *aNode = static_cast<ISimpleDOMNode*>(new sdnAccessible(resultNode)); 1.357 + (*aNode)->AddRef(); 1.358 + } 1.359 + 1.360 + return S_OK; 1.361 + 1.362 + A11Y_TRYBLOCK_END 1.363 +} 1.364 + 1.365 +STDMETHODIMP 1.366 +sdnAccessible::get_lastChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode) 1.367 +{ 1.368 + A11Y_TRYBLOCK_BEGIN 1.369 + 1.370 + if (!aNode) 1.371 + return E_INVALIDARG; 1.372 + *aNode = nullptr; 1.373 + 1.374 + if (IsDefunct()) 1.375 + return CO_E_OBJNOTCONNECTED; 1.376 + 1.377 + nsINode* resultNode = mNode->GetLastChild(); 1.378 + if (resultNode) { 1.379 + *aNode = static_cast<ISimpleDOMNode*>(new sdnAccessible(resultNode)); 1.380 + (*aNode)->AddRef(); 1.381 + } 1.382 + 1.383 + return S_OK; 1.384 + 1.385 + A11Y_TRYBLOCK_END 1.386 +} 1.387 + 1.388 +STDMETHODIMP 1.389 +sdnAccessible::get_previousSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode) 1.390 +{ 1.391 + A11Y_TRYBLOCK_BEGIN 1.392 + 1.393 + if (!aNode) 1.394 + return E_INVALIDARG; 1.395 + *aNode = nullptr; 1.396 + 1.397 + if (IsDefunct()) 1.398 + return CO_E_OBJNOTCONNECTED; 1.399 + 1.400 + nsINode* resultNode = mNode->GetPreviousSibling(); 1.401 + if (resultNode) { 1.402 + *aNode = static_cast<ISimpleDOMNode*>(new sdnAccessible(resultNode)); 1.403 + (*aNode)->AddRef(); 1.404 + } 1.405 + 1.406 + return S_OK; 1.407 + 1.408 + A11Y_TRYBLOCK_END 1.409 +} 1.410 + 1.411 +STDMETHODIMP 1.412 +sdnAccessible::get_nextSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode) 1.413 +{ 1.414 + A11Y_TRYBLOCK_BEGIN 1.415 + 1.416 + if (!aNode) 1.417 + return E_INVALIDARG; 1.418 + *aNode = nullptr; 1.419 + 1.420 + if (IsDefunct()) 1.421 + return CO_E_OBJNOTCONNECTED; 1.422 + 1.423 + nsINode* resultNode = mNode->GetNextSibling(); 1.424 + if (resultNode) { 1.425 + *aNode = static_cast<ISimpleDOMNode*>(new sdnAccessible(resultNode)); 1.426 + (*aNode)->AddRef(); 1.427 + } 1.428 + 1.429 + return S_OK; 1.430 + 1.431 + A11Y_TRYBLOCK_END 1.432 +} 1.433 + 1.434 +STDMETHODIMP 1.435 +sdnAccessible::get_childAt(unsigned aChildIndex, 1.436 + ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode) 1.437 +{ 1.438 + A11Y_TRYBLOCK_BEGIN 1.439 + 1.440 + if (!aNode) 1.441 + return E_INVALIDARG; 1.442 + *aNode = nullptr; 1.443 + 1.444 + if (IsDefunct()) 1.445 + return CO_E_OBJNOTCONNECTED; 1.446 + 1.447 + nsINode* resultNode = mNode->GetChildAt(aChildIndex); 1.448 + if (resultNode) { 1.449 + *aNode = static_cast<ISimpleDOMNode*>(new sdnAccessible(resultNode)); 1.450 + (*aNode)->AddRef(); 1.451 + } 1.452 + 1.453 + 1.454 + return S_OK; 1.455 + 1.456 + A11Y_TRYBLOCK_END 1.457 +} 1.458 + 1.459 +STDMETHODIMP 1.460 +sdnAccessible::get_innerHTML(BSTR __RPC_FAR* aInnerHTML) 1.461 +{ 1.462 + A11Y_TRYBLOCK_BEGIN 1.463 + 1.464 + if (!aInnerHTML) 1.465 + return E_INVALIDARG; 1.466 + *aInnerHTML = nullptr; 1.467 + 1.468 + if (IsDefunct()) 1.469 + return CO_E_OBJNOTCONNECTED; 1.470 + 1.471 + if (!mNode->IsElement()) 1.472 + return S_FALSE; 1.473 + 1.474 + nsAutoString innerHTML; 1.475 + mNode->AsElement()->GetInnerHTML(innerHTML); 1.476 + if (innerHTML.IsEmpty()) 1.477 + return S_FALSE; 1.478 + 1.479 + *aInnerHTML = ::SysAllocStringLen(innerHTML.get(), innerHTML.Length()); 1.480 + if (!*aInnerHTML) 1.481 + return E_OUTOFMEMORY; 1.482 + 1.483 + return S_OK; 1.484 + 1.485 + A11Y_TRYBLOCK_END 1.486 +} 1.487 + 1.488 +STDMETHODIMP 1.489 +sdnAccessible::get_localInterface(void __RPC_FAR *__RPC_FAR* aLocalInterface) 1.490 +{ 1.491 + A11Y_TRYBLOCK_BEGIN 1.492 + 1.493 + if (!aLocalInterface) 1.494 + return E_INVALIDARG; 1.495 + *aLocalInterface = nullptr; 1.496 + 1.497 + if (IsDefunct()) 1.498 + return CO_E_OBJNOTCONNECTED; 1.499 + 1.500 + *aLocalInterface = this; 1.501 + AddRef(); 1.502 + 1.503 + return S_OK; 1.504 + 1.505 + A11Y_TRYBLOCK_END 1.506 +} 1.507 + 1.508 +STDMETHODIMP 1.509 +sdnAccessible::get_language(BSTR __RPC_FAR* aLanguage) 1.510 +{ 1.511 + A11Y_TRYBLOCK_BEGIN 1.512 + 1.513 + if (!aLanguage) 1.514 + return E_INVALIDARG; 1.515 + *aLanguage = nullptr; 1.516 + 1.517 + if (IsDefunct()) 1.518 + return CO_E_OBJNOTCONNECTED; 1.519 + 1.520 + nsAutoString language; 1.521 + if (mNode->IsContent()) 1.522 + nsCoreUtils::GetLanguageFor(mNode->AsContent(), nullptr, language); 1.523 + if (language.IsEmpty()) { // Nothing found, so use document's language 1.524 + mNode->OwnerDoc()->GetHeaderData(nsGkAtoms::headerContentLanguage, 1.525 + language); 1.526 + } 1.527 + 1.528 + if (language.IsEmpty()) 1.529 + return S_FALSE; 1.530 + 1.531 + *aLanguage = ::SysAllocStringLen(language.get(), language.Length()); 1.532 + if (!*aLanguage) 1.533 + return E_OUTOFMEMORY; 1.534 + 1.535 + return S_OK; 1.536 + 1.537 + A11Y_TRYBLOCK_END 1.538 +}