summaryrefslogtreecommitdiffstats
path: root/accessible/windows/sdn
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/windows/sdn')
-rw-r--r--accessible/windows/sdn/moz.build26
-rw-r--r--accessible/windows/sdn/sdnAccessible-inl.h49
-rw-r--r--accessible/windows/sdn/sdnAccessible.cpp522
-rw-r--r--accessible/windows/sdn/sdnAccessible.h149
-rw-r--r--accessible/windows/sdn/sdnDocAccessible.cpp117
-rw-r--r--accessible/windows/sdn/sdnDocAccessible.h52
-rw-r--r--accessible/windows/sdn/sdnTextAccessible.cpp166
-rw-r--r--accessible/windows/sdn/sdnTextAccessible.h69
8 files changed, 1150 insertions, 0 deletions
diff --git a/accessible/windows/sdn/moz.build b/accessible/windows/sdn/moz.build
new file mode 100644
index 0000000000..4d6ed60a18
--- /dev/null
+++ b/accessible/windows/sdn/moz.build
@@ -0,0 +1,26 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+UNIFIED_SOURCES += [
+ "sdnAccessible.cpp",
+ "sdnDocAccessible.cpp",
+ "sdnTextAccessible.cpp",
+]
+
+LOCAL_INCLUDES += [
+ "/accessible/base",
+ "/accessible/generic",
+ "/accessible/html",
+ "/accessible/windows/msaa",
+ "/accessible/xpcom",
+ "/accessible/xul",
+]
+
+include("/ipc/chromium/chromium-config.mozbuild")
+
+FINAL_LIBRARY = "xul"
+
+REQUIRES_UNIFIED_BUILD = True
diff --git a/accessible/windows/sdn/sdnAccessible-inl.h b/accessible/windows/sdn/sdnAccessible-inl.h
new file mode 100644
index 0000000000..76f8796f42
--- /dev/null
+++ b/accessible/windows/sdn/sdnAccessible-inl.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_a11y_sdnAccessible_inl_h_
+#define mozilla_a11y_sdnAccessible_inl_h_
+
+#include "sdnAccessible.h"
+
+#include "DocAccessible.h"
+#include "nsAccessibilityService.h"
+
+namespace mozilla {
+namespace a11y {
+
+inline DocAccessible* sdnAccessible::GetDocument() const {
+ MOZ_ASSERT(mNode);
+ return GetExistingDocAccessible(mNode->OwnerDoc());
+}
+
+inline MsaaAccessible* sdnAccessible::GetMsaa() {
+ if (mMsaa) {
+ return mMsaa;
+ }
+
+ DocAccessible* document = GetDocument();
+ if (!document) {
+ return nullptr;
+ }
+
+ // Once we have an accessible, we should hold a reference to it so that we
+ // may preserve object identity.
+ AccessibleWrap* wrap = static_cast<AccessibleWrap*>(
+ document->GetAccessibleEvenIfNotInMap(mNode));
+
+ if (!wrap) {
+ return nullptr;
+ }
+
+ wrap->GetNativeInterface(getter_AddRefs(mMsaa));
+ return mMsaa;
+}
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif // mozilla_a11y_sdnAccessible_inl_h_
diff --git a/accessible/windows/sdn/sdnAccessible.cpp b/accessible/windows/sdn/sdnAccessible.cpp
new file mode 100644
index 0000000000..c1bbbb7e2f
--- /dev/null
+++ b/accessible/windows/sdn/sdnAccessible.cpp
@@ -0,0 +1,522 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "sdnAccessible-inl.h"
+#include "ISimpleDOM_i.c"
+
+#include "DocAccessibleWrap.h"
+
+#include "nsAttrName.h"
+#include "nsCoreUtils.h"
+#include "nsIAccessibleTypes.h"
+#include "nsICSSDeclaration.h"
+#include "nsNameSpaceManager.h"
+#include "nsServiceManagerUtils.h"
+#include "nsWinUtils.h"
+#include "nsRange.h"
+
+#include "mozilla/dom/BorrowedAttrInfo.h"
+#include "mozilla/dom/Document.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/ErrorResult.h"
+#include "mozilla/PresShell.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+
+sdnAccessible::~sdnAccessible() {
+ if (mUniqueId.isSome()) {
+ MsaaAccessible::ReleaseChildID(WrapNotNull(this));
+ }
+}
+
+STDMETHODIMP
+sdnAccessible::QueryInterface(REFIID aREFIID, void** aInstancePtr) {
+ if (!aInstancePtr) return E_FAIL;
+ *aInstancePtr = nullptr;
+
+ if (aREFIID == IID_IClientSecurity) {
+ // Some code might QI(IID_IClientSecurity) to detect whether or not we are
+ // a proxy. Right now that can potentially happen off the main thread, so we
+ // look for this condition immediately so that we don't trigger other code
+ // that might not be thread-safe.
+ return E_NOINTERFACE;
+ }
+
+ if (aREFIID == IID_ISimpleDOMNode) {
+ *aInstancePtr = static_cast<ISimpleDOMNode*>(this);
+ AddRef();
+ return S_OK;
+ }
+
+ MsaaAccessible* accessible = GetMsaa();
+ if (accessible) return accessible->QueryInterface(aREFIID, aInstancePtr);
+
+ // IUnknown* is the canonical one if and only if this accessible doesn't have
+ // an accessible.
+ if (aREFIID == IID_IUnknown) {
+ *aInstancePtr = static_cast<ISimpleDOMNode*>(this);
+ AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP
+sdnAccessible::get_nodeInfo(BSTR __RPC_FAR* aNodeName,
+ short __RPC_FAR* aNameSpaceID,
+ BSTR __RPC_FAR* aNodeValue,
+ unsigned int __RPC_FAR* aNumChildren,
+ unsigned int __RPC_FAR* aUniqueID,
+ unsigned short __RPC_FAR* aNodeType) {
+ if (!aNodeName || !aNameSpaceID || !aNodeValue || !aNumChildren ||
+ !aUniqueID || !aNodeType)
+ return E_INVALIDARG;
+
+ *aNodeName = nullptr;
+ *aNameSpaceID = 0;
+ *aNodeValue = nullptr;
+ *aNumChildren = 0;
+ *aUniqueID = 0;
+ *aNodeType = 0;
+
+ if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
+
+ // This is a unique ID for every content node. The 3rd party accessibility
+ // application can compare this to the childID we return for events such as
+ // focus events, to correlate back to data nodes in their internal object
+ // model.
+ MsaaAccessible* accessible = GetMsaa();
+ if (accessible) {
+ *aUniqueID = MsaaAccessible::GetChildIDFor(accessible->Acc());
+ } else {
+ if (mUniqueId.isNothing()) {
+ MsaaAccessible::AssignChildIDTo(WrapNotNull(this));
+ }
+ MOZ_ASSERT(mUniqueId.isSome());
+ *aUniqueID = mUniqueId.value();
+ }
+
+ if (!mNode) {
+ RemoteAccessible* remoteAcc = accessible->Acc()->AsRemote();
+ MOZ_ASSERT(remoteAcc);
+ if (remoteAcc->IsText()) {
+ *aNodeType = nsINode::TEXT_NODE;
+ } else if (remoteAcc->IsDoc()) {
+ *aNodeType = nsINode::DOCUMENT_NODE;
+ } else {
+ *aNodeType = nsINode::ELEMENT_NODE;
+ }
+ if (nsAtom* tag = remoteAcc->TagName()) {
+ nsAutoString nodeName;
+ tag->ToString(nodeName);
+ *aNodeName = ::SysAllocString(nodeName.get());
+ }
+ return S_OK;
+ }
+
+ uint16_t nodeType = mNode->NodeType();
+ *aNodeType = static_cast<unsigned short>(nodeType);
+
+ if (*aNodeType != NODETYPE_TEXT) {
+ *aNodeName = ::SysAllocString(mNode->NodeName().get());
+ }
+
+ nsAutoString nodeValue;
+ mNode->GetNodeValue(nodeValue);
+ *aNodeValue = ::SysAllocString(nodeValue.get());
+
+ *aNameSpaceID = mNode->IsContent()
+ ? static_cast<short>(mNode->AsContent()->GetNameSpaceID())
+ : 0;
+
+ *aNumChildren = mNode->GetChildCount();
+
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnAccessible::get_attributes(unsigned short aMaxAttribs,
+ BSTR __RPC_FAR* aAttribNames,
+ short __RPC_FAR* aNameSpaceIDs,
+ BSTR __RPC_FAR* aAttribValues,
+ unsigned short __RPC_FAR* aNumAttribs) {
+ if (!aAttribNames || !aNameSpaceIDs || !aAttribValues || !aNumAttribs)
+ return E_INVALIDARG;
+
+ *aNumAttribs = 0;
+
+ if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
+ if (!mNode) {
+ MOZ_ASSERT(mMsaa && mMsaa->Acc()->IsRemote());
+ return E_NOTIMPL;
+ }
+
+ if (!mNode->IsElement()) return S_FALSE;
+
+ dom::Element* elm = mNode->AsElement();
+ uint32_t numAttribs = elm->GetAttrCount();
+ if (numAttribs > aMaxAttribs) numAttribs = aMaxAttribs;
+
+ *aNumAttribs = static_cast<unsigned short>(numAttribs);
+
+ for (uint32_t index = 0; index < numAttribs; index++) {
+ aNameSpaceIDs[index] = 0;
+ aAttribValues[index] = aAttribNames[index] = nullptr;
+ nsAutoString attributeValue;
+
+ dom::BorrowedAttrInfo attr = elm->GetAttrInfoAt(index);
+ attr.mValue->ToString(attributeValue);
+
+ aNameSpaceIDs[index] = static_cast<short>(attr.mName->NamespaceID());
+ aAttribNames[index] =
+ ::SysAllocString(attr.mName->LocalName()->GetUTF16String());
+ aAttribValues[index] = ::SysAllocString(attributeValue.get());
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnAccessible::get_attributesForNames(unsigned short aMaxAttribs,
+ BSTR __RPC_FAR* aAttribNames,
+ short __RPC_FAR* aNameSpaceID,
+ BSTR __RPC_FAR* aAttribValues) {
+ if (!aAttribNames || !aNameSpaceID || !aAttribValues) return E_INVALIDARG;
+
+ if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
+ if (!mNode) {
+ MOZ_ASSERT(mMsaa && mMsaa->Acc()->IsRemote());
+ // NVDA expects this to succeed for MathML and won't call innerHTML if this
+ // fails. Therefore, return S_FALSE here instead of E_NOTIMPL, indicating
+ // that the attributes aren't present.
+ return S_FALSE;
+ }
+
+ if (!mNode->IsElement()) return S_FALSE;
+
+ dom::Element* domElement = mNode->AsElement();
+ nsNameSpaceManager* nameSpaceManager = nsNameSpaceManager::GetInstance();
+
+ int32_t index = 0;
+ for (index = 0; index < aMaxAttribs; index++) {
+ aAttribValues[index] = nullptr;
+ if (aAttribNames[index]) {
+ nsAutoString attributeValue, nameSpaceURI;
+ nsAutoString attributeName(
+ nsDependentString(static_cast<const wchar_t*>(aAttribNames[index])));
+
+ if (aNameSpaceID[index] > 0 &&
+ NS_SUCCEEDED(nameSpaceManager->GetNameSpaceURI(aNameSpaceID[index],
+ nameSpaceURI))) {
+ domElement->GetAttributeNS(nameSpaceURI, attributeName, attributeValue);
+ } else {
+ domElement->GetAttribute(attributeName, attributeValue);
+ }
+
+ aAttribValues[index] = ::SysAllocString(attributeValue.get());
+ }
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnAccessible::get_computedStyle(
+ unsigned short aMaxStyleProperties, boolean aUseAlternateView,
+ BSTR __RPC_FAR* aStyleProperties, BSTR __RPC_FAR* aStyleValues,
+ unsigned short __RPC_FAR* aNumStyleProperties) {
+ if (!aStyleProperties || aStyleValues || !aNumStyleProperties)
+ return E_INVALIDARG;
+
+ if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
+ if (!mNode) {
+ MOZ_ASSERT(mMsaa && mMsaa->Acc()->IsRemote());
+ return E_NOTIMPL;
+ }
+
+ *aNumStyleProperties = 0;
+
+ if (mNode->IsDocument()) return S_FALSE;
+
+ nsCOMPtr<nsICSSDeclaration> cssDecl =
+ nsWinUtils::GetComputedStyleDeclaration(mNode->AsContent());
+ NS_ENSURE_TRUE(cssDecl, E_FAIL);
+
+ uint32_t length = cssDecl->Length();
+
+ uint32_t index = 0, realIndex = 0;
+ for (index = realIndex = 0; index < length && realIndex < aMaxStyleProperties;
+ index++) {
+ nsAutoCString property;
+ nsAutoCString value;
+
+ // Ignore -moz-* properties.
+ cssDecl->Item(index, property);
+ if (property.CharAt(0) != '-')
+ cssDecl->GetPropertyValue(property, value); // Get property value
+
+ if (!value.IsEmpty()) {
+ aStyleProperties[realIndex] =
+ ::SysAllocString(NS_ConvertUTF8toUTF16(property).get());
+ aStyleValues[realIndex] =
+ ::SysAllocString(NS_ConvertUTF8toUTF16(value).get());
+ ++realIndex;
+ }
+ }
+
+ *aNumStyleProperties = static_cast<unsigned short>(realIndex);
+
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnAccessible::get_computedStyleForProperties(
+ unsigned short aNumStyleProperties, boolean aUseAlternateView,
+ BSTR __RPC_FAR* aStyleProperties, BSTR __RPC_FAR* aStyleValues) {
+ if (!aStyleProperties || !aStyleValues) return E_INVALIDARG;
+
+ if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
+ if (!mNode) {
+ MOZ_ASSERT(mMsaa && mMsaa->Acc()->IsRemote());
+ return E_NOTIMPL;
+ }
+
+ if (mNode->IsDocument()) return S_FALSE;
+
+ nsCOMPtr<nsICSSDeclaration> cssDecl =
+ nsWinUtils::GetComputedStyleDeclaration(mNode->AsContent());
+ NS_ENSURE_TRUE(cssDecl, E_FAIL);
+
+ uint32_t index = 0;
+ for (index = 0; index < aNumStyleProperties; index++) {
+ nsAutoCString value;
+ if (aStyleProperties[index])
+ cssDecl->GetPropertyValue(
+ NS_ConvertUTF16toUTF8(nsDependentString(aStyleProperties[index])),
+ value); // Get property value
+ aStyleValues[index] = ::SysAllocString(NS_ConvertUTF8toUTF16(value).get());
+ }
+
+ return S_OK;
+}
+
+// XXX Use MOZ_CAN_RUN_SCRIPT_BOUNDARY for now due to bug 1543294.
+MOZ_CAN_RUN_SCRIPT_BOUNDARY STDMETHODIMP
+sdnAccessible::scrollTo(boolean aScrollTopLeft) {
+ if (IsDefunct()) {
+ return CO_E_OBJNOTCONNECTED;
+ }
+ if (!mNode) {
+ MOZ_ASSERT(mMsaa && mMsaa->Acc()->IsRemote());
+ return E_NOTIMPL;
+ }
+
+ DocAccessible* document = GetDocument();
+ MOZ_ASSERT(document);
+ if (!mNode->IsContent()) return S_FALSE;
+
+ uint32_t scrollType = aScrollTopLeft
+ ? nsIAccessibleScrollType::SCROLL_TYPE_TOP_LEFT
+ : nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_RIGHT;
+
+ RefPtr<PresShell> presShell = document->PresShellPtr();
+ nsCOMPtr<nsIContent> content = mNode->AsContent();
+ nsCoreUtils::ScrollTo(presShell, content, scrollType);
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnAccessible::get_parentNode(ISimpleDOMNode __RPC_FAR* __RPC_FAR* aNode) {
+ if (!aNode) return E_INVALIDARG;
+ *aNode = nullptr;
+
+ if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
+ if (!mNode) {
+ MOZ_ASSERT(mMsaa && mMsaa->Acc()->IsRemote());
+ return E_NOTIMPL;
+ }
+
+ nsINode* resultNode = mNode->GetParentNode();
+ if (resultNode) {
+ *aNode = static_cast<ISimpleDOMNode*>(new sdnAccessible(resultNode));
+ (*aNode)->AddRef();
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnAccessible::get_firstChild(ISimpleDOMNode __RPC_FAR* __RPC_FAR* aNode) {
+ if (!aNode) return E_INVALIDARG;
+ *aNode = nullptr;
+
+ if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
+ if (!mNode) {
+ MOZ_ASSERT(mMsaa && mMsaa->Acc()->IsRemote());
+ return E_NOTIMPL;
+ }
+
+ nsINode* resultNode = mNode->GetFirstChild();
+ if (resultNode) {
+ *aNode = static_cast<ISimpleDOMNode*>(new sdnAccessible(resultNode));
+ (*aNode)->AddRef();
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnAccessible::get_lastChild(ISimpleDOMNode __RPC_FAR* __RPC_FAR* aNode) {
+ if (!aNode) return E_INVALIDARG;
+ *aNode = nullptr;
+
+ if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
+ if (!mNode) {
+ MOZ_ASSERT(mMsaa && mMsaa->Acc()->IsRemote());
+ return E_NOTIMPL;
+ }
+
+ nsINode* resultNode = mNode->GetLastChild();
+ if (resultNode) {
+ *aNode = static_cast<ISimpleDOMNode*>(new sdnAccessible(resultNode));
+ (*aNode)->AddRef();
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnAccessible::get_previousSibling(ISimpleDOMNode __RPC_FAR* __RPC_FAR* aNode) {
+ if (!aNode) return E_INVALIDARG;
+ *aNode = nullptr;
+
+ if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
+ if (!mNode) {
+ MOZ_ASSERT(mMsaa && mMsaa->Acc()->IsRemote());
+ return E_NOTIMPL;
+ }
+
+ nsINode* resultNode = mNode->GetPreviousSibling();
+ if (resultNode) {
+ *aNode = static_cast<ISimpleDOMNode*>(new sdnAccessible(resultNode));
+ (*aNode)->AddRef();
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnAccessible::get_nextSibling(ISimpleDOMNode __RPC_FAR* __RPC_FAR* aNode) {
+ if (!aNode) return E_INVALIDARG;
+ *aNode = nullptr;
+
+ if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
+ if (!mNode) {
+ MOZ_ASSERT(mMsaa && mMsaa->Acc()->IsRemote());
+ return E_NOTIMPL;
+ }
+
+ nsINode* resultNode = mNode->GetNextSibling();
+ if (resultNode) {
+ *aNode = static_cast<ISimpleDOMNode*>(new sdnAccessible(resultNode));
+ (*aNode)->AddRef();
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnAccessible::get_childAt(unsigned aChildIndex,
+ ISimpleDOMNode __RPC_FAR* __RPC_FAR* aNode) {
+ if (!aNode) return E_INVALIDARG;
+ *aNode = nullptr;
+
+ if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
+ if (!mNode) {
+ MOZ_ASSERT(mMsaa && mMsaa->Acc()->IsRemote());
+ return E_NOTIMPL;
+ }
+
+ nsINode* resultNode = mNode->GetChildAt_Deprecated(aChildIndex);
+ if (resultNode) {
+ *aNode = static_cast<ISimpleDOMNode*>(new sdnAccessible(resultNode));
+ (*aNode)->AddRef();
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnAccessible::get_innerHTML(BSTR __RPC_FAR* aInnerHTML) {
+ if (!aInnerHTML) return E_INVALIDARG;
+ *aInnerHTML = nullptr;
+
+ if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
+
+ nsAutoString innerHTML;
+ if (!mNode) {
+ RemoteAccessible* remoteAcc = mMsaa->Acc()->AsRemote();
+ MOZ_ASSERT(remoteAcc);
+ if (!remoteAcc->mCachedFields) {
+ return S_FALSE;
+ }
+ remoteAcc->mCachedFields->GetAttribute(nsGkAtoms::html, innerHTML);
+ } else {
+ if (!mNode->IsElement()) {
+ return S_FALSE;
+ }
+ mNode->AsElement()->GetInnerHTML(innerHTML, IgnoreErrors());
+ }
+
+ if (innerHTML.IsEmpty()) return S_FALSE;
+
+ *aInnerHTML = ::SysAllocStringLen(innerHTML.get(), innerHTML.Length());
+ if (!*aInnerHTML) return E_OUTOFMEMORY;
+
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnAccessible::get_localInterface(void __RPC_FAR* __RPC_FAR* aLocalInterface) {
+ if (!aLocalInterface) return E_INVALIDARG;
+ *aLocalInterface = nullptr;
+
+ if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
+
+ *aLocalInterface = this;
+ AddRef();
+
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnAccessible::get_language(BSTR __RPC_FAR* aLanguage) {
+ if (!aLanguage) return E_INVALIDARG;
+ *aLanguage = nullptr;
+
+ if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
+ if (!mNode) {
+ MOZ_ASSERT(mMsaa && mMsaa->Acc()->IsRemote());
+ return E_NOTIMPL;
+ }
+
+ nsAutoString language;
+ if (mNode->IsContent())
+ nsCoreUtils::GetLanguageFor(mNode->AsContent(), nullptr, language);
+ if (language.IsEmpty()) { // Nothing found, so use document's language
+ mNode->OwnerDoc()->GetHeaderData(nsGkAtoms::headerContentLanguage,
+ language);
+ }
+
+ if (language.IsEmpty()) return S_FALSE;
+
+ *aLanguage = ::SysAllocStringLen(language.get(), language.Length());
+ if (!*aLanguage) return E_OUTOFMEMORY;
+
+ return S_OK;
+}
diff --git a/accessible/windows/sdn/sdnAccessible.h b/accessible/windows/sdn/sdnAccessible.h
new file mode 100644
index 0000000000..610a4ca5de
--- /dev/null
+++ b/accessible/windows/sdn/sdnAccessible.h
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_a11y_sdnAccessible_h_
+#define mozilla_a11y_sdnAccessible_h_
+
+#include "ISimpleDOM.h"
+#include "AccessibleWrap.h"
+#include "IUnknownImpl.h"
+#include "MsaaAccessible.h"
+
+#include "mozilla/Attributes.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/NotNull.h"
+
+namespace mozilla {
+namespace a11y {
+
+class sdnAccessible final : public ISimpleDOMNode {
+ public:
+ explicit sdnAccessible(nsINode* aNode) : mNode(aNode) {
+ if (!mNode) MOZ_CRASH();
+ }
+
+ explicit sdnAccessible(NotNull<MsaaAccessible*> aMsaa) : mMsaa(aMsaa) {
+ Accessible* acc = aMsaa->Acc();
+ MOZ_ASSERT(acc);
+ if (LocalAccessible* localAcc = acc->AsLocal()) {
+ mNode = localAcc->GetNode();
+ }
+ }
+
+ ~sdnAccessible();
+
+ /**
+ * Return if the object is defunct.
+ */
+ bool IsDefunct() const {
+ if (mMsaa && !mMsaa->Acc()) {
+ return true;
+ }
+ if (!mNode) {
+ MOZ_ASSERT(mMsaa && mMsaa->Acc()->IsRemote());
+ return false;
+ }
+ return !GetDocument();
+ }
+
+ /**
+ * Return a local document accessible it belongs to if any.
+ */
+ DocAccessible* GetDocument() const;
+
+ /*
+ * Return associated MsaaAccessible if any.
+ */
+ MsaaAccessible* GetMsaa();
+
+ void SetUniqueID(uint32_t aNewUniqueId) { mUniqueId = Some(aNewUniqueId); }
+
+ Maybe<uint32_t> ReleaseUniqueID() {
+ Maybe<uint32_t> result = mUniqueId;
+ mUniqueId = Nothing();
+ return result;
+ }
+
+ // IUnknown
+ DECL_IUNKNOWN
+
+ virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_nodeInfo(
+ /* [out] */ BSTR __RPC_FAR* aNodeName,
+ /* [out] */ short __RPC_FAR* aNameSpaceID,
+ /* [out] */ BSTR __RPC_FAR* aNodeValue,
+ /* [out] */ unsigned int __RPC_FAR* aNumChildren,
+ /* [out] */ unsigned int __RPC_FAR* aUniqueID,
+ /* [out][retval] */ unsigned short __RPC_FAR* aNodeType);
+
+ virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_attributes(
+ /* [in] */ unsigned short aMaxAttribs,
+ /* [length_is][size_is][out] */ BSTR __RPC_FAR* aAttribNames,
+ /* [length_is][size_is][out] */ short __RPC_FAR* aNameSpaceIDs,
+ /* [length_is][size_is][out] */ BSTR __RPC_FAR* aAttribValues,
+ /* [out][retval] */ unsigned short __RPC_FAR* aNumAttribs);
+
+ virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_attributesForNames(
+ /* [in] */ unsigned short aMaxAttribs,
+ /* [length_is][size_is][in] */ BSTR __RPC_FAR* aAttribNames,
+ /* [length_is][size_is][in] */ short __RPC_FAR* aNameSpaceID,
+ /* [length_is][size_is][retval] */ BSTR __RPC_FAR* aAttribValues);
+
+ virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_computedStyle(
+ /* [in] */ unsigned short aMaxStyleProperties,
+ /* [in] */ boolean aUseAlternateView,
+ /* [length_is][size_is][out] */ BSTR __RPC_FAR* aStyleProperties,
+ /* [length_is][size_is][out] */ BSTR __RPC_FAR* aStyleValues,
+ /* [out][retval] */ unsigned short __RPC_FAR* aNumStyleProperties);
+
+ virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE
+ get_computedStyleForProperties(
+ /* [in] */ unsigned short aNumStyleProperties,
+ /* [in] */ boolean aUseAlternateView,
+ /* [length_is][size_is][in] */ BSTR __RPC_FAR* aStyleProperties,
+ /* [length_is][size_is][out][retval] */ BSTR __RPC_FAR* aStyleValues);
+
+ virtual HRESULT STDMETHODCALLTYPE scrollTo(/* [in] */ boolean aScrollTopLeft);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_parentNode(
+ /* [out][retval] */ ISimpleDOMNode __RPC_FAR* __RPC_FAR* aNode);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_firstChild(
+ /* [out][retval] */ ISimpleDOMNode __RPC_FAR* __RPC_FAR* aNode);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_lastChild(
+ /* [out][retval] */ ISimpleDOMNode __RPC_FAR* __RPC_FAR* aNode);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_previousSibling(
+ /* [out][retval] */ ISimpleDOMNode __RPC_FAR* __RPC_FAR* aNode);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_nextSibling(
+ /* [out][retval] */ ISimpleDOMNode __RPC_FAR* __RPC_FAR* aNode);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_childAt(
+ /* [in] */ unsigned aChildIndex,
+ /* [out][retval] */ ISimpleDOMNode __RPC_FAR* __RPC_FAR* aNode);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_innerHTML(
+ /* [out][retval] */ BSTR __RPC_FAR* aInnerHTML);
+
+ virtual /* [local][propget] */ HRESULT STDMETHODCALLTYPE get_localInterface(
+ /* [retval][out] */ void __RPC_FAR* __RPC_FAR* aLocalInterface);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_language(
+ /* [out][retval] */ BSTR __RPC_FAR* aLanguage);
+
+ private:
+ // mNode will be null for a RemoteAccessible. In that case, we only partially
+ // implement this interface using data from the RemoteAccessible cache.
+ nsCOMPtr<nsINode> mNode;
+ RefPtr<MsaaAccessible> mMsaa;
+ Maybe<uint32_t> mUniqueId;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif // mozilla_a11y_sdnAccessible_h_
diff --git a/accessible/windows/sdn/sdnDocAccessible.cpp b/accessible/windows/sdn/sdnDocAccessible.cpp
new file mode 100644
index 0000000000..e773f1a5a0
--- /dev/null
+++ b/accessible/windows/sdn/sdnDocAccessible.cpp
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "sdnDocAccessible.h"
+
+#include "LocalAccessible-inl.h"
+#include "ISimpleDOM.h"
+
+#include "nsNameSpaceManager.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+
+////////////////////////////////////////////////////////////////////////////////
+// sdnDocAccessible
+////////////////////////////////////////////////////////////////////////////////
+
+IMPL_IUNKNOWN_QUERY_HEAD(sdnDocAccessible)
+IMPL_IUNKNOWN_QUERY_IFACE(ISimpleDOMDocument)
+IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mMsaa)
+
+STDMETHODIMP
+sdnDocAccessible::get_URL(BSTR __RPC_FAR* aURL) {
+ if (!aURL) return E_INVALIDARG;
+ *aURL = nullptr;
+
+ DocAccessible* acc = mMsaa->DocAcc();
+ if (!acc) return CO_E_OBJNOTCONNECTED;
+
+ nsAutoString URL;
+ acc->URL(URL);
+ if (URL.IsEmpty()) return S_FALSE;
+
+ *aURL = ::SysAllocStringLen(URL.get(), URL.Length());
+ return *aURL ? S_OK : E_OUTOFMEMORY;
+}
+
+STDMETHODIMP
+sdnDocAccessible::get_title(BSTR __RPC_FAR* aTitle) {
+ if (!aTitle) return E_INVALIDARG;
+ *aTitle = nullptr;
+
+ DocAccessible* acc = mMsaa->DocAcc();
+ if (!acc) return CO_E_OBJNOTCONNECTED;
+
+ nsAutoString title;
+ acc->Title(title);
+ *aTitle = ::SysAllocStringLen(title.get(), title.Length());
+ return *aTitle ? S_OK : E_OUTOFMEMORY;
+}
+
+STDMETHODIMP
+sdnDocAccessible::get_mimeType(BSTR __RPC_FAR* aMimeType) {
+ if (!aMimeType) return E_INVALIDARG;
+ *aMimeType = nullptr;
+
+ DocAccessible* acc = mMsaa->DocAcc();
+ if (!acc) return CO_E_OBJNOTCONNECTED;
+
+ nsAutoString mimeType;
+ acc->MimeType(mimeType);
+ if (mimeType.IsEmpty()) return S_FALSE;
+
+ *aMimeType = ::SysAllocStringLen(mimeType.get(), mimeType.Length());
+ return *aMimeType ? S_OK : E_OUTOFMEMORY;
+}
+
+STDMETHODIMP
+sdnDocAccessible::get_docType(BSTR __RPC_FAR* aDocType) {
+ if (!aDocType) return E_INVALIDARG;
+ *aDocType = nullptr;
+
+ DocAccessible* acc = mMsaa->DocAcc();
+ if (!acc) return CO_E_OBJNOTCONNECTED;
+
+ nsAutoString docType;
+ acc->DocType(docType);
+ if (docType.IsEmpty()) return S_FALSE;
+
+ *aDocType = ::SysAllocStringLen(docType.get(), docType.Length());
+ return *aDocType ? S_OK : E_OUTOFMEMORY;
+}
+
+STDMETHODIMP
+sdnDocAccessible::get_nameSpaceURIForID(short aNameSpaceID,
+ BSTR __RPC_FAR* aNameSpaceURI) {
+ if (!aNameSpaceURI) return E_INVALIDARG;
+ *aNameSpaceURI = nullptr;
+
+ if (!mMsaa->DocAcc()) return CO_E_OBJNOTCONNECTED;
+
+ if (aNameSpaceID < 0) return E_INVALIDARG; // -1 is kNameSpaceID_Unknown
+
+ nsAutoString nameSpaceURI;
+ nsNameSpaceManager* nameSpaceManager = nsNameSpaceManager::GetInstance();
+ if (nameSpaceManager)
+ nameSpaceManager->GetNameSpaceURI(aNameSpaceID, nameSpaceURI);
+
+ if (nameSpaceURI.IsEmpty()) return S_FALSE;
+
+ *aNameSpaceURI =
+ ::SysAllocStringLen(nameSpaceURI.get(), nameSpaceURI.Length());
+
+ return *aNameSpaceURI ? S_OK : E_OUTOFMEMORY;
+}
+
+STDMETHODIMP
+sdnDocAccessible::put_alternateViewMediaTypes(
+ BSTR __RPC_FAR* aCommaSeparatedMediaTypes) {
+ if (!aCommaSeparatedMediaTypes) return E_INVALIDARG;
+ *aCommaSeparatedMediaTypes = nullptr;
+
+ return !mMsaa->DocAcc() ? CO_E_OBJNOTCONNECTED : E_NOTIMPL;
+}
diff --git a/accessible/windows/sdn/sdnDocAccessible.h b/accessible/windows/sdn/sdnDocAccessible.h
new file mode 100644
index 0000000000..452b43ec85
--- /dev/null
+++ b/accessible/windows/sdn/sdnDocAccessible.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_a11y_sdnDocAccessible_h_
+#define mozilla_a11y_sdnDocAccessible_h_
+
+#include "ISimpleDOM.h"
+#include "IUnknownImpl.h"
+
+#include "MsaaDocAccessible.h"
+
+namespace mozilla {
+namespace a11y {
+
+class sdnDocAccessible final : public ISimpleDOMDocument {
+ public:
+ explicit sdnDocAccessible(MsaaDocAccessible* aMsaa) : mMsaa(aMsaa){};
+ ~sdnDocAccessible(){};
+
+ DECL_IUNKNOWN
+
+ // ISimpleDOMDocument
+ virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_URL(
+ /* [out] */ BSTR __RPC_FAR* url);
+
+ virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_title(
+ /* [out] */ BSTR __RPC_FAR* title);
+
+ virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_mimeType(
+ /* [out] */ BSTR __RPC_FAR* mimeType);
+
+ virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_docType(
+ /* [out] */ BSTR __RPC_FAR* docType);
+
+ virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_nameSpaceURIForID(
+ /* [in] */ short nameSpaceID,
+ /* [out] */ BSTR __RPC_FAR* nameSpaceURI);
+
+ virtual /* [id] */ HRESULT STDMETHODCALLTYPE put_alternateViewMediaTypes(
+ /* [in] */ BSTR __RPC_FAR* commaSeparatedMediaTypes);
+
+ protected:
+ RefPtr<MsaaDocAccessible> mMsaa;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/windows/sdn/sdnTextAccessible.cpp b/accessible/windows/sdn/sdnTextAccessible.cpp
new file mode 100644
index 0000000000..73ef4eb6e8
--- /dev/null
+++ b/accessible/windows/sdn/sdnTextAccessible.cpp
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "sdnTextAccessible.h"
+
+#include "ISimpleDOM.h"
+
+#include "nsCoreUtils.h"
+#include "DocAccessible.h"
+
+#include "nsIFrame.h"
+#include "nsFontMetrics.h"
+#include "nsPresContext.h"
+#include "nsLayoutUtils.h"
+#include "nsRange.h"
+#include "gfxTextRun.h"
+#include "nsIAccessibleTypes.h"
+#include "mozilla/gfx/2D.h"
+
+using namespace mozilla::a11y;
+
+////////////////////////////////////////////////////////////////////////////////
+// sdnTextAccessible
+////////////////////////////////////////////////////////////////////////////////
+
+IMPL_IUNKNOWN_QUERY_HEAD(sdnTextAccessible)
+IMPL_IUNKNOWN_QUERY_IFACE(ISimpleDOMText)
+IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mMsaa)
+
+STDMETHODIMP
+sdnTextAccessible::get_domText(BSTR __RPC_FAR* aText) {
+ if (!aText) return E_INVALIDARG;
+ *aText = nullptr;
+
+ AccessibleWrap* acc = mMsaa->LocalAcc();
+ if (!acc) return CO_E_OBJNOTCONNECTED;
+
+ nsAutoString nodeValue;
+
+ acc->GetContent()->GetNodeValue(nodeValue);
+ if (nodeValue.IsEmpty()) return S_FALSE;
+
+ *aText = ::SysAllocStringLen(nodeValue.get(), nodeValue.Length());
+ return *aText ? S_OK : E_OUTOFMEMORY;
+}
+
+STDMETHODIMP
+sdnTextAccessible::get_clippedSubstringBounds(
+ unsigned int aStartIndex, unsigned int aEndIndex, int __RPC_FAR* aX,
+ int __RPC_FAR* aY, int __RPC_FAR* aWidth, int __RPC_FAR* aHeight) {
+ nscoord x = 0, y = 0, width = 0, height = 0;
+ HRESULT rv = get_unclippedSubstringBounds(aStartIndex, aEndIndex, &x, &y,
+ &width, &height);
+ if (FAILED(rv)) return rv;
+
+ DocAccessible* document = mMsaa->LocalAcc()->Document();
+ NS_ASSERTION(
+ document,
+ "There must always be a doc accessible, but there isn't. Crash!");
+
+ LayoutDeviceIntRect docRect = document->Bounds();
+ LayoutDeviceIntRect unclippedRect(x, y, width, height);
+
+ LayoutDeviceIntRect clippedRect;
+ clippedRect.IntersectRect(unclippedRect, docRect);
+
+ *aX = clippedRect.X();
+ *aY = clippedRect.Y();
+ *aWidth = clippedRect.Width();
+ *aHeight = clippedRect.Height();
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnTextAccessible::get_unclippedSubstringBounds(
+ unsigned int aStartIndex, unsigned int aEndIndex, int __RPC_FAR* aX,
+ int __RPC_FAR* aY, int __RPC_FAR* aWidth, int __RPC_FAR* aHeight) {
+ if (!aX || !aY || !aWidth || !aHeight) return E_INVALIDARG;
+ *aX = *aY = *aWidth = *aHeight = 0;
+
+ AccessibleWrap* acc = mMsaa->LocalAcc();
+ if (!acc) return CO_E_OBJNOTCONNECTED;
+
+ nsIFrame* frame = acc->GetFrame();
+ NS_ENSURE_TRUE(frame, E_FAIL);
+
+ nsPoint startPoint, endPoint;
+ nsIFrame* startFrame =
+ GetPointFromOffset(frame, aStartIndex, true, startPoint);
+ nsIFrame* endFrame = GetPointFromOffset(frame, aEndIndex, false, endPoint);
+ if (!startFrame || !endFrame) return E_FAIL;
+
+ nsRect sum;
+ nsIFrame* iter = startFrame;
+ nsIFrame* stopLoopFrame = endFrame->GetNextContinuation();
+ for (; iter != stopLoopFrame; iter = iter->GetNextContinuation()) {
+ nsRect rect = iter->GetScreenRectInAppUnits();
+ nscoord start = (iter == startFrame) ? startPoint.x : 0;
+ nscoord end = (iter == endFrame) ? endPoint.x : rect.Width();
+ rect.MoveByX(start);
+ rect.SetWidth(end - start);
+ sum.UnionRect(sum, rect);
+ }
+
+ nsPresContext* presContext = acc->Document()->PresContext();
+ *aX = presContext->AppUnitsToDevPixels(sum.X());
+ *aY = presContext->AppUnitsToDevPixels(sum.Y());
+ *aWidth = presContext->AppUnitsToDevPixels(sum.Width());
+ *aHeight = presContext->AppUnitsToDevPixels(sum.Height());
+
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnTextAccessible::scrollToSubstring(unsigned int aStartIndex,
+ unsigned int aEndIndex) {
+ AccessibleWrap* acc = mMsaa->LocalAcc();
+ if (!acc) return CO_E_OBJNOTCONNECTED;
+
+ RefPtr<nsRange> range = nsRange::Create(acc->GetContent());
+ if (NS_FAILED(range->SetStart(acc->GetContent(), aStartIndex))) return E_FAIL;
+
+ if (NS_FAILED(range->SetEnd(acc->GetContent(), aEndIndex))) return E_FAIL;
+
+ nsresult rv = nsCoreUtils::ScrollSubstringTo(
+ acc->GetFrame(), range, nsIAccessibleScrollType::SCROLL_TYPE_ANYWHERE);
+ return GetHRESULT(rv);
+}
+
+STDMETHODIMP
+sdnTextAccessible::get_fontFamily(BSTR __RPC_FAR* aFontFamily) {
+ if (!aFontFamily) return E_INVALIDARG;
+ *aFontFamily = nullptr;
+
+ AccessibleWrap* acc = mMsaa->LocalAcc();
+ if (!acc) return CO_E_OBJNOTCONNECTED;
+
+ nsIFrame* frame = acc->GetFrame();
+ if (!frame) return E_FAIL;
+
+ RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetFontMetricsForFrame(frame, 1.0f);
+ RefPtr<gfxFont> font = fm->GetThebesFontGroup()->GetFirstValidFont();
+
+ const nsCString& name = font->GetName();
+ if (name.IsEmpty()) return S_FALSE;
+
+ NS_ConvertUTF8toUTF16 str(name);
+ *aFontFamily = ::SysAllocStringLen(str.get(), str.Length());
+ return *aFontFamily ? S_OK : E_OUTOFMEMORY;
+}
+
+nsIFrame* sdnTextAccessible::GetPointFromOffset(nsIFrame* aContainingFrame,
+ int32_t aOffset,
+ bool aPreferNext,
+ nsPoint& aOutPoint) {
+ nsIFrame* textFrame = nullptr;
+ int32_t outOffset;
+ aContainingFrame->GetChildFrameContainingOffset(aOffset, aPreferNext,
+ &outOffset, &textFrame);
+ if (textFrame) textFrame->GetPointFromOffset(aOffset, &aOutPoint);
+
+ return textFrame;
+}
diff --git a/accessible/windows/sdn/sdnTextAccessible.h b/accessible/windows/sdn/sdnTextAccessible.h
new file mode 100644
index 0000000000..3f93c20fcc
--- /dev/null
+++ b/accessible/windows/sdn/sdnTextAccessible.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_a11y_sdnTextAccessible_h_
+#define mozilla_a11y_sdnTextAccessible_h_
+
+#include "ISimpleDOM.h"
+#include "IUnknownImpl.h"
+
+#include "MsaaAccessible.h"
+
+class nsIFrame;
+struct nsPoint;
+
+namespace mozilla {
+namespace a11y {
+
+class sdnTextAccessible final : public ISimpleDOMText {
+ public:
+ explicit sdnTextAccessible(MsaaAccessible* aMsaa) : mMsaa(aMsaa){};
+ ~sdnTextAccessible() {}
+
+ DECL_IUNKNOWN
+
+ // ISimpleDOMText
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_domText(
+ /* [retval][out] */ BSTR __RPC_FAR* aText);
+
+ virtual HRESULT STDMETHODCALLTYPE get_clippedSubstringBounds(
+ /* [in] */ unsigned int startIndex,
+ /* [in] */ unsigned int endIndex,
+ /* [out] */ int __RPC_FAR* aX,
+ /* [out] */ int __RPC_FAR* aY,
+ /* [out] */ int __RPC_FAR* aWidth,
+ /* [out] */ int __RPC_FAR* aHeight);
+
+ virtual HRESULT STDMETHODCALLTYPE get_unclippedSubstringBounds(
+ /* [in] */ unsigned int aStartIndex,
+ /* [in] */ unsigned int aEndIndex,
+ /* [out] */ int __RPC_FAR* aX,
+ /* [out] */ int __RPC_FAR* aY,
+ /* [out] */ int __RPC_FAR* aWidth,
+ /* [out] */ int __RPC_FAR* aHeight);
+
+ virtual HRESULT STDMETHODCALLTYPE scrollToSubstring(
+ /* [in] */ unsigned int aStartIndex,
+ /* [in] */ unsigned int aEndIndex);
+
+ virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_fontFamily(
+ /* [retval][out] */ BSTR __RPC_FAR* aFontFamily);
+
+ private:
+ /**
+ * Return child frame containing offset on success.
+ */
+ nsIFrame* GetPointFromOffset(nsIFrame* aContainingFrame, int32_t aOffset,
+ bool aPreferNext, nsPoint& aOutPoint);
+
+ RefPtr<MsaaAccessible> mMsaa;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif