diff options
Diffstat (limited to 'accessible/ipc/win/handler/HandlerRelation.cpp')
-rw-r--r-- | accessible/ipc/win/handler/HandlerRelation.cpp | 138 |
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 |