summaryrefslogtreecommitdiffstats
path: root/accessible/ipc/win/handler/HandlerRelation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/ipc/win/handler/HandlerRelation.cpp')
-rw-r--r--accessible/ipc/win/handler/HandlerRelation.cpp138
1 files changed, 138 insertions, 0 deletions
diff --git a/accessible/ipc/win/handler/HandlerRelation.cpp b/accessible/ipc/win/handler/HandlerRelation.cpp
new file mode 100644
index 0000000000..8e03da5360
--- /dev/null
+++ b/accessible/ipc/win/handler/HandlerRelation.cpp
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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/. */
+
+#if defined(MOZILLA_INTERNAL_API)
+# error This code is NOT for internal Gecko use!
+#endif // defined(MOZILLA_INTERNAL_API)
+
+#include "HandlerRelation.h"
+#include "mozilla/Assertions.h"
+
+#include "AccessibleRelation_i.c"
+
+namespace mozilla {
+namespace a11y {
+
+HandlerRelation::HandlerRelation(AccessibleHandler* aHandler,
+ IARelationData& aData)
+ : mHandler(aHandler), mData(aData), mTargets(nullptr) {
+ // This instance now owns any pointers, so ensure no one else can
+ // manipulate them.
+ aData.mType = nullptr;
+}
+
+HandlerRelation::~HandlerRelation() {
+ if (mData.mType) {
+ ::SysFreeString(mData.mType);
+ }
+
+ if (mTargets) {
+ for (long index = 0; index < mData.mNTargets; ++index) {
+ mTargets[index]->Release();
+ }
+ ::CoTaskMemFree(mTargets);
+ mTargets = nullptr;
+ }
+}
+
+HRESULT
+HandlerRelation::GetTargets() {
+ if (mTargets) {
+ // Already cached.
+ return S_OK;
+ }
+
+ // Marshaling all of the IAccessibleRelation objects across processes is
+ // slow, and the client probably only wants targets for a few of them.
+ // Therefore, we just use IAccessible2_2::relationTargetsOfType, passing
+ // the type we have cached. This is a bit inefficient because Gecko has
+ // to look up the relation twice, but it's significantly faster than
+ // marshaling the relation objects regardless.
+ return mHandler->get_relationTargetsOfType(mData.mType, 0, &mTargets,
+ &mData.mNTargets);
+}
+
+IMPL_IUNKNOWN1(HandlerRelation, IAccessibleRelation)
+
+/*** IAccessibleRelation ***/
+
+HRESULT
+HandlerRelation::get_relationType(BSTR* aType) {
+ if (!aType) {
+ return E_INVALIDARG;
+ }
+ if (!mData.mType) {
+ return E_FAIL;
+ }
+ *aType = CopyBSTR(mData.mType);
+ return S_OK;
+}
+
+HRESULT
+HandlerRelation::get_localizedRelationType(BSTR* aLocalizedType) {
+ // This is not implemented as per ia2AccessibleRelation.
+ return E_NOTIMPL;
+}
+
+HRESULT
+HandlerRelation::get_nTargets(long* aNTargets) {
+ if (!aNTargets) {
+ return E_INVALIDARG;
+ }
+ if (mData.mNTargets == -1) {
+ return E_FAIL;
+ }
+ *aNTargets = mData.mNTargets;
+ return S_OK;
+}
+
+HRESULT
+HandlerRelation::get_target(long aIndex, IUnknown** aTarget) {
+ if (!aTarget) {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr = GetTargets();
+ if (FAILED(hr)) {
+ return hr;
+ }
+ if (aIndex >= mData.mNTargets) {
+ return E_INVALIDARG;
+ }
+
+ *aTarget = mTargets[aIndex];
+ (*aTarget)->AddRef();
+ return S_OK;
+}
+
+HRESULT
+HandlerRelation::get_targets(long aMaxTargets, IUnknown** aTargets,
+ long* aNTargets) {
+ if (aMaxTargets == 0 || !aTargets || !aNTargets) {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr = GetTargets();
+ if (FAILED(hr)) {
+ return hr;
+ }
+
+ if (mData.mNTargets > aMaxTargets) {
+ // Don't give back more targets than were requested.
+ *aNTargets = aMaxTargets;
+ } else {
+ *aNTargets = mData.mNTargets;
+ }
+
+ for (long index = 0; index < *aNTargets; ++index) {
+ aTargets[index] = mTargets[index];
+ aTargets[index]->AddRef();
+ }
+ return S_OK;
+}
+
+} // namespace a11y
+} // namespace mozilla