--- a/accessible/ipc/win/handler/AccessibleHandler.cpp
+++ b/accessible/ipc/win/handler/AccessibleHandler.cpp
@@ -23,16 +23,17 @@
#include <objbase.h>
#include <uiautomation.h>
#include <winreg.h>
#include "AccessibleHypertext.h"
#include "Accessible2_i.c"
#include "Accessible2_2_i.c"
#include "Accessible2_3_i.c"
+#include "AccessibleHyperlink_i.c"
namespace mozilla {
namespace a11y {
static mscom::Factory<AccessibleHandler> sHandlerFactory;
HRESULT
AccessibleHandler::Create(IUnknown* aOuter, REFIID aIid, void** aOutInterface)
@@ -55,16 +56,17 @@ AccessibleHandler::Create(IUnknown* aOut
return handler->InternalQueryInterface(aIid, aOutInterface);
}
AccessibleHandler::AccessibleHandler(IUnknown* aOuter, HRESULT* aResult)
: mscom::Handler(aOuter, aResult)
, mDispatch(nullptr)
, mIA2PassThru(nullptr)
, mServProvPassThru(nullptr)
+ , mIAHyperlinkPassThru(nullptr)
, mCachedData()
, mCacheGen(0)
{
RefPtr<AccessibleHandlerControl> ctl(gControlFactory.GetOrCreateSingleton());
MOZ_ASSERT(ctl);
if (!ctl) {
if (aResult) {
*aResult = E_UNEXPECTED;
@@ -100,16 +102,39 @@ AccessibleHandler::ResolveIA2()
// mIA2PassThru is a weak reference (see comments in AccesssibleHandler.h)
mIA2PassThru->Release();
}
return hr;
}
HRESULT
+AccessibleHandler::ResolveIAHyperlink()
+{
+ if (mIAHyperlinkPassThru) {
+ return S_OK;
+ }
+
+ RefPtr<IUnknown> proxy(GetProxy());
+ if (!proxy) {
+ return E_UNEXPECTED;
+ }
+
+ HRESULT hr = proxy->QueryInterface(IID_IAccessibleHyperlink,
+ reinterpret_cast<void**>(&mIAHyperlinkPassThru));
+ if (SUCCEEDED(hr)) {
+ // mIAHyperlinkPassThru is a weak reference
+ // (see comments in AccesssibleHandler.h)
+ mIAHyperlinkPassThru->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
AccessibleHandler::MaybeUpdateCachedData()
{
RefPtr<AccessibleHandlerControl> ctl(gControlFactory.GetOrCreateSingleton());
if (!ctl) {
return E_OUTOFMEMORY;
}
uint32_t gen = ctl->GetCacheGen();
@@ -387,16 +412,18 @@ CopyBSTR(BSTR aSrc)
assignTo = mCachedData.mData.member; \
}
#define GET_BSTR(member, assignTo) \
{ \
assignTo = CopyBSTR(mCachedData.mData.member); \
}
+/*** IAccessible ***/
+
HRESULT
AccessibleHandler::get_accParent(IDispatch **ppdispParent)
{
HRESULT hr = ResolveIA2();
if (FAILED(hr)) {
return hr;
}
return mIA2PassThru->get_accParent(ppdispParent);
@@ -704,16 +731,18 @@ AccessibleHandler::put_accName(VARIANT v
HRESULT
AccessibleHandler::put_accValue(VARIANT varChild, BSTR szValue)
{
// This matches AccessibleWrap
return E_NOTIMPL;
}
+/*** IAccessible2 ***/
+
HRESULT
AccessibleHandler::get_nRelations(long* nRelations)
{
HRESULT hr = ResolveIA2();
if (FAILED(hr)) {
return hr;
}
return mIA2PassThru->get_nRelations(nRelations);
@@ -961,16 +990,18 @@ AccessibleHandler::get_attributes(BSTR*
return mIA2PassThru->get_attributes(attributes);
}
BEGIN_CACHE_ACCESS;
GET_BSTR(mAttributes, *attributes);
return S_OK;
}
+/*** IAccessible2_2 ***/
+
HRESULT
AccessibleHandler::get_attribute(BSTR name, VARIANT* attribute)
{
// Not yet implemented by ia2Accessible.
// Once ia2Accessible implements this, we could either pass it through
// or we could extract these individually from cached mAttributes.
// The latter should be considered if traffic warrants it.
return E_NOTIMPL;
@@ -995,16 +1026,18 @@ AccessibleHandler::get_relationTargetsOf
HRESULT hr = ResolveIA2();
if (FAILED(hr)) {
return hr;
}
return mIA2PassThru->get_relationTargetsOfType(type, maxTargets, targets,
nTargets);
}
+/*** IAccessible2_3 ***/
+
HRESULT
AccessibleHandler::get_selectionRanges(IA2Range** ranges, long* nRanges)
{
HRESULT hr = ResolveIA2();
if (FAILED(hr)) {
return hr;
}
return mIA2PassThru->get_selectionRanges(ranges, nRanges);
@@ -1018,16 +1051,18 @@ static const GUID kUnsupportedServices[]
// Unknown, queried by Windows
{0x8EDAA462, 0x21F4, 0x4C87, { 0xA0, 0x12, 0xB3, 0xCD, 0xA3, 0xAB, 0x01, 0xFC }},
// Unknown, queried by Windows
{0xacd46652, 0x829d, 0x41cb, { 0xa5, 0xfc, 0x17, 0xac, 0xf4, 0x36, 0x61, 0xac }},
// Unknown, queried by Windows
{0xb96fdb85, 0x7204, 0x4724, { 0x84, 0x2b, 0xc7, 0x05, 0x9d, 0xed, 0xb9, 0xd0 }}
};
+/*** IServiceProvider ***/
+
HRESULT
AccessibleHandler::QueryService(REFGUID aServiceId, REFIID aIid,
void** aOutInterface)
{
static_assert(&NEWEST_IA2_IID == &IID_IAccessible2_3,
"You have modified NEWEST_IA2_IID. This code needs updating.");
/* We're taking advantage of the fact that we are implementing IA2 as part
of our own object to implement this just like a QI. */
@@ -1059,27 +1094,147 @@ AccessibleHandler::QueryService(REFGUID
// mServProvPassThru is a weak reference (see comments in
// AccessibleHandler.h)
mServProvPassThru->Release();
}
return mServProvPassThru->QueryService(aServiceId, aIid, aOutInterface);
}
+/*** IProvideClassInfo ***/
+
HRESULT
AccessibleHandler::GetClassInfo(ITypeInfo** aOutTypeInfo)
{
RefPtr<AccessibleHandlerControl> ctl(gControlFactory.GetOrCreateSingleton());
if (!ctl) {
return E_OUTOFMEMORY;
}
return ctl->GetHandlerTypeInfo(aOutTypeInfo);
}
+/*** IAccessibleAction ***/
+
+HRESULT
+AccessibleHandler::nActions(long* nActions)
+{
+ HRESULT hr = ResolveIAHyperlink();
+ if (FAILED(hr)) {
+ return hr;
+ }
+ return mIAHyperlinkPassThru->nActions(nActions);
+}
+
+HRESULT
+AccessibleHandler::doAction(long actionIndex)
+{
+ HRESULT hr = ResolveIAHyperlink();
+ if (FAILED(hr)) {
+ return hr;
+ }
+ return mIAHyperlinkPassThru->doAction(actionIndex);
+}
+
+HRESULT
+AccessibleHandler::get_description(long actionIndex, BSTR* description)
+{
+ HRESULT hr = ResolveIAHyperlink();
+ if (FAILED(hr)) {
+ return hr;
+ }
+ return mIAHyperlinkPassThru->get_description(actionIndex, description);
+}
+
+HRESULT
+AccessibleHandler::get_keyBinding(long actionIndex,
+ long nMaxBindings,
+ BSTR** keyBindings,
+ long* nBindings)
+{
+ HRESULT hr = ResolveIAHyperlink();
+ if (FAILED(hr)) {
+ return hr;
+ }
+ return mIAHyperlinkPassThru->get_keyBinding(
+ actionIndex, nMaxBindings, keyBindings, nBindings);
+}
+
+HRESULT
+AccessibleHandler::get_name(long actionIndex, BSTR* name)
+{
+ HRESULT hr = ResolveIAHyperlink();
+ if (FAILED(hr)) {
+ return hr;
+ }
+ return mIAHyperlinkPassThru->get_name(actionIndex, name);
+}
+
+HRESULT
+AccessibleHandler::get_localizedName(long actionIndex, BSTR* localizedName)
+{
+ HRESULT hr = ResolveIAHyperlink();
+ if (FAILED(hr)) {
+ return hr;
+ }
+ return mIAHyperlinkPassThru->get_localizedName(actionIndex, localizedName);
+}
+
+/*** IAccessibleHyperlink ***/
+
+HRESULT
+AccessibleHandler::get_anchor(long index, VARIANT* anchor)
+{
+ HRESULT hr = ResolveIAHyperlink();
+ if (FAILED(hr)) {
+ return hr;
+ }
+ return mIAHyperlinkPassThru->get_anchor(index, anchor);
+}
+
+HRESULT
+AccessibleHandler::get_anchorTarget(long index, VARIANT* anchorTarget)
+{
+ HRESULT hr = ResolveIAHyperlink();
+ if (FAILED(hr)) {
+ return hr;
+ }
+ return mIAHyperlinkPassThru->get_anchorTarget(index, anchorTarget);
+}
+
+HRESULT
+AccessibleHandler::get_startIndex(long* index)
+{
+ HRESULT hr = ResolveIAHyperlink();
+ if (FAILED(hr)) {
+ return hr;
+ }
+ return mIAHyperlinkPassThru->get_startIndex(index);
+}
+
+HRESULT
+AccessibleHandler::get_endIndex(long* index)
+{
+ HRESULT hr = ResolveIAHyperlink();
+ if (FAILED(hr)) {
+ return hr;
+ }
+ return mIAHyperlinkPassThru->get_endIndex(index);
+}
+
+HRESULT
+AccessibleHandler::get_valid(boolean* valid)
+{
+ HRESULT hr = ResolveIAHyperlink();
+ if (FAILED(hr)) {
+ return hr;
+ }
+ return mIAHyperlinkPassThru->get_valid(valid);
+}
+
} // namespace a11y
} // namespace mozilla
extern "C" HRESULT __stdcall
ProxyDllCanUnloadNow();
extern "C" HRESULT __stdcall
DllCanUnloadNow()
--- a/accessible/ipc/win/handler/AccessibleHandler.h
+++ b/accessible/ipc/win/handler/AccessibleHandler.h
@@ -30,30 +30,32 @@ import NEWEST_IA2_IDL;
#include "HandlerData.h"
#include <windows.h>
#if !defined(MOZILLA_INTERNAL_API)
#include "Accessible2_3.h"
+#include "AccessibleHyperlink.h"
#include "Handler.h"
#include "mozilla/mscom/StructStream.h"
#include "mozilla/UniquePtr.h"
#include <ocidl.h>
#include <servprov.h>
namespace mozilla {
namespace a11y {
class AccessibleHandler final : public mscom::Handler
, public NEWEST_IA2_INTERFACE
, public IServiceProvider
, public IProvideClassInfo
+ , public IAccessibleHyperlink
{
public:
static HRESULT Create(IUnknown* aOuter, REFIID aIid, void** aOutInterface);
// mscom::Handler
HRESULT QueryHandlerInterface(IUnknown* aProxyUnknown, REFIID aIid,
void** aOutInterface) override;
HRESULT ReadHandlerPayload(IStream* aStream, REFIID aIid) override;
@@ -147,22 +149,42 @@ public:
// IServiceProvider
STDMETHODIMP QueryService(REFGUID aServiceId, REFIID aIid,
void** aOutInterface) override;
// IProvideClassInfo
STDMETHODIMP GetClassInfo(ITypeInfo** aOutTypeInfo) override;
+ // IAccessibleAction
+ STDMETHODIMP nActions(long* nActions) override;
+ STDMETHODIMP doAction(long actionIndex) override;
+ STDMETHODIMP get_description(long actionIndex, BSTR* description) override;
+ STDMETHODIMP get_keyBinding(long actionIndex,
+ long nMaxBindings,
+ BSTR** keyBindings,
+ long* nBindings) override;
+ STDMETHODIMP get_name(long actionIndex, BSTR* name) override;
+ STDMETHODIMP get_localizedName(long actionIndex,
+ BSTR* localizedName) override;
+
+ // IAccessibleHyperlink
+ STDMETHODIMP get_anchor(long index, VARIANT* anchor) override;
+ STDMETHODIMP get_anchorTarget(long index, VARIANT* anchorTarget) override;
+ STDMETHODIMP get_startIndex(long* index) override;
+ STDMETHODIMP get_endIndex(long* index) override;
+ STDMETHODIMP get_valid(boolean* valid) override;
+
private:
AccessibleHandler(IUnknown* aOuter, HRESULT* aResult);
virtual ~AccessibleHandler();
HRESULT ResolveIA2();
HRESULT ResolveIDispatch();
+ HRESULT ResolveIAHyperlink();
HRESULT MaybeUpdateCachedData();
RefPtr<IUnknown> mDispatchUnk;
/**
* Handlers aggregate their proxies. This means that their proxies delegate
* their IUnknown implementation to us.
*
* mDispatchUnk and the result of Handler::GetProxy() are both strong
@@ -178,16 +200,17 @@ private:
* must immediately Release() them to prevent these cycles.
*
* It is safe for us to use these raw pointers because the aggregated
* objects's lifetimes are proper subsets of our own lifetime.
*/
IDispatch* mDispatch; // weak
NEWEST_IA2_INTERFACE* mIA2PassThru; // weak
IServiceProvider* mServProvPassThru; // weak
+ IAccessibleHyperlink* mIAHyperlinkPassThru; // weak
IA2Payload mCachedData;
UniquePtr<mscom::StructToStream> mSerializer;
uint32_t mCacheGen;
};
} // namespace a11y
} // namespace mozilla