Bug 1821963 part 3: Remove various components supporting the old accessibility architecture based on content process COM proxies. r=nlapre,nalexander

This includes AccessibleHandler, HandlerProvider, IGeckoCustom and the IAccessible2 COM proxy dll.
Even with the new architecture, we still use IAccessible2, but we no longer need a COM proxy because we aren't using COM across processes ourselves.
If clients want to use IAccessible2 across processes, they're responsible for registering a COM proxy themselves as with all other IAccessible2 applications.
Alternatively, they can rely on the IAccessible2 COM proxy which is included with Windows 10 and later.

Differential Revision: https://phabricator.services.mozilla.com/D177963
This commit is contained in:
James Teh 2023-05-22 10:00:21 +00:00
parent 13afc4eeb2
commit 3a3b50114d
49 changed files with 22 additions and 5842 deletions

View File

@ -58,11 +58,6 @@ bool ShouldA11yBeEnabled();
#endif
#if defined(XP_WIN)
/*
* Do we have AccessibleHandler.dll registered.
*/
bool IsHandlerRegistered();
/*
* Name of platform service that instantiated accessibility
*/

View File

@ -1,32 +0,0 @@
/* -*- 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/. */
import "objidl.idl";
import "oaidl.idl";
[object, uuid(7510360f-cdae-4de9-88c8-d167eda62afc)]
interface IGeckoCustom : IUnknown
{
[propget] HRESULT ID([out, retval] unsigned __int64* aID);
[propget] HRESULT anchorCount([out, retval] long* aCount);
[propget] HRESULT boundsInCSSPixels([out] __int32* aX,
[out] __int32* aY,
[out] __int32* aWidth,
[out, retval] __int32* aHeight);
[propget] HRESULT DOMNodeID([out, retval] BSTR* aID);
[propget] HRESULT minimumIncrement([out, retval] double* aIncrement);
[propget] HRESULT mozState([out, retval] unsigned __int64* aState);
}
[
uuid(55769d85-f830-4d76-9e39-3670914a28f7),
helpstring("private custom gecko interfaces")
]
library IGeckoCustom
{
interface IGeckoCustom;
};

View File

@ -1,39 +0,0 @@
# -*- 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/.
GeneratedFile(
"IGeckoCustom.h",
"IGeckoCustom_p.c",
"IGeckoCustom_i.c",
"IGeckoCustom_dlldata.c",
"IGeckoCustom.tlb",
inputs=["IGeckoCustom.idl"],
script="/build/midl.py",
entry_point="midl",
flags=["-dlldata", OBJDIR + "/IGeckoCustom_dlldata.c"],
)
SOURCES += [
"!IGeckoCustom_dlldata.c",
"!IGeckoCustom_i.c",
"!IGeckoCustom_p.c",
]
EXPORTS += [
"!IGeckoCustom.h",
"!IGeckoCustom_i.c",
]
FINAL_LIBRARY = "xul"
# Suppress warnings from the MIDL generated code.
if CONFIG["CC_TYPE"] == "clang-cl":
CFLAGS += [
"-Wno-extern-initializer",
"-Wno-incompatible-pointer-types",
"-Wno-missing-braces",
"-Wno-unused-const-variable",
]

View File

@ -1,11 +0,0 @@
;+# 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/.
LIBRARY IA2Marshal.dll
EXPORTS DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
GetProxyDllInfo PRIVATE

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="IA2Marshal" version="1.0.0.0" />
<file name="IA2Marshal.dll">
<comInterfaceProxyStub
iid="{E89F726E-C4F4-4c19-BB19-B647D7FA8478}"
proxyStubClsid32="{E89F726E-C4F4-4c19-BB19-B647D7FA8478}"
name="IAccessible2"
tlbid="{CE3F726E-D1D3-44FE-B995-FF1DB3B48B2B}"
/>
</file>
</assembly>

View File

@ -1,5 +0,0 @@
/* 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/. */
1 typelib IA2Typelib.tlb

View File

@ -1,61 +0,0 @@
/* -*- 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/. */
typedef struct _MozRemotableHandle
{
long fContext;
long hRemote;
} MozRemotableHandle;
typedef [unique] MozRemotableHandle * mozHWND;
typedef [unique] MozRemotableHandle * mozHMENU;
typedef [unique] MozRemotableHandle * mozHACCEL;
typedef [unique] MozRemotableHandle * mozHBRUSH;
typedef [unique] MozRemotableHandle * mozHFONT;
typedef [unique] MozRemotableHandle * mozHDC;
typedef [unique] MozRemotableHandle * mozHICON;
typedef [unique] MozRemotableHandle * mozHRGN;
typedef [unique] MozRemotableHandle * mozHMONITOR;
cpp_quote("#if 0")
typedef [wire_marshal(mozHWND)] void* HWND;
typedef [wire_marshal(mozHMENU)] void* HMENU;
typedef [wire_marshal(mozHACCEL)] void* HACCEL;
typedef [wire_marshal(mozHBRUSH)] void* HBRUSH;
typedef [wire_marshal(mozHFONT)] void* HFONT;
typedef [wire_marshal(mozHDC)] void* HDC;
typedef [wire_marshal(mozHICON)] void* HICON;
typedef [wire_marshal(mozHRGN)] void* HRGN;
typedef [wire_marshal(mozHMONITOR)] void* HMONITOR;
cpp_quote("#endif // 0")
import "Accessible2.idl";
import "Accessible2_2.idl";
import "Accessible2_3.idl";
import "AccessibleAction.idl";
import "AccessibleApplication.idl";
import "AccessibleComponent.idl";
import "AccessibleDocument.idl";
import "AccessibleEditableText.idl";
import "AccessibleEventId.idl";
import "AccessibleHyperlink.idl";
import "AccessibleHypertext.idl";
import "AccessibleHypertext2.idl";
import "AccessibleImage.idl";
import "AccessibleRelation.idl";
import "AccessibleRole.idl";
import "AccessibleStates.idl";
import "AccessibleTable.idl";
import "AccessibleTable2.idl";
import "AccessibleTableCell.idl";
import "AccessibleText.idl";
import "AccessibleText2.idl";
import "AccessibleValue.idl";
import "IA2CommonTypes.idl";
// We are explicitly using #include instead of import so that the imported
// IDL is treated as part of this IDL file.
#include "IA2TypeLibrary.idl"

View File

@ -4,20 +4,6 @@
# 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/.
GeckoSharedLibrary("IA2Marshal", linkage=None)
DEFINES["REGISTER_PROXY_DLL"] = True
DEFFILE = "IA2Marshal.def"
OS_LIBS += [
"uuid",
"kernel32",
"rpcrt4",
"ole32",
"oleaut32",
]
midl_enums = [
"AccessibleEventId",
"AccessibleRole",
@ -90,42 +76,3 @@ for iface in midl_interfaces:
SOURCES["!%s" % p].flags += [
"-DUserMarshalRoutines=UserMarshalRoutines__%s" % p[:-2]
]
# Warning: the build system doesn't know about the dependency of IA2Marshal.rc on
# IA2Typelib.tlb. We rely on the IA2Typelib.h output forcing the command to run
# during export, before rc files are treated during compile.
GeneratedFile(
"IA2Typelib.h",
"IA2Typelib_i.c",
"IA2Typelib.tlb",
inputs=["IA2Typelib.idl"],
script="/build/midl.py",
entry_point="midl",
flags=[
"-app_config",
"-I",
TOPSRCDIR + "/other-licenses/ia2",
"-D",
"_MIDL_DECLARE_WIREM_HANDLE",
],
)
GeneratedFile(
"dlldata.c",
inputs=["!" + iface + "_dlldata.c" for iface in midl_interfaces],
script="/build/midl.py",
entry_point="merge_dlldata",
)
SOURCES += ["!dlldata.c"]
RCINCLUDE = "IA2Marshal.rc"
# Suppress warnings from the MIDL generated code.
if CONFIG["CC_TYPE"] == "clang-cl":
CFLAGS += [
"-Wno-extern-initializer",
"-Wno-incompatible-pointer-types",
"-Wno-missing-braces",
"-Wno-unused-const-variable",
]

View File

@ -5,7 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows" and CONFIG["COMPILE_ENVIRONMENT"]:
DIRS += ["gecko", "msaa", "ia2"]
DIRS += ["msaa", "ia2"]
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
XPIDL_SOURCES += ["nsIAccessibleMacInterface.idl"]

View File

@ -1,969 +0,0 @@
/* -*- 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/. */
#include "mozilla/a11y/HandlerProvider.h"
#include <memory.h>
#include <utility>
#include "Accessible2_3.h"
#include "AccessibleApplication.h"
#include "AccessibleDocument.h"
#include "AccessibleDocument_i.c"
#include "AccessibleEditableText.h"
#include "AccessibleImage.h"
#include "AccessibleRelation.h"
#include "AccessibleTable.h"
#include "AccessibleTable2.h"
#include "AccessibleTableCell.h"
#include "HandlerData.h"
#include "HandlerData_i.c"
#include "ISimpleDOM.h"
#include "mozilla/Assertions.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/a11y/AccessibleWrap.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/mscom/AgileReference.h"
#include "mozilla/mscom/FastMarshaler.h"
#include "mozilla/mscom/Interceptor.h"
#include "mozilla/mscom/MainThreadHandoff.h"
#include "mozilla/mscom/MainThreadInvoker.h"
#include "mozilla/mscom/Ptr.h"
#include "mozilla/mscom/StructStream.h"
#include "mozilla/mscom/Utils.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
#include "uiautomation.h"
namespace mozilla {
namespace a11y {
HandlerProvider::HandlerProvider(REFIID aIid,
mscom::InterceptorTargetPtr<IUnknown> aTarget)
: mRefCnt(0),
mMutex("mozilla::a11y::HandlerProvider::mMutex"),
mTargetUnkIid(aIid),
mTargetUnk(std::move(aTarget)),
mPayloadMutex("mozilla::a11y::HandlerProvider::mPayloadMutex") {}
HRESULT
HandlerProvider::QueryInterface(REFIID riid, void** ppv) {
if (!ppv) {
return E_INVALIDARG;
}
if (riid == IID_IUnknown || riid == IID_IGeckoBackChannel) {
RefPtr<IUnknown> punk(static_cast<IGeckoBackChannel*>(this));
punk.forget(ppv);
return S_OK;
}
if (riid == IID_IMarshal) {
if (!mFastMarshalUnk) {
HRESULT hr =
mscom::FastMarshaler::Create(static_cast<IGeckoBackChannel*>(this),
getter_AddRefs(mFastMarshalUnk));
if (FAILED(hr)) {
return hr;
}
}
return mFastMarshalUnk->QueryInterface(riid, ppv);
}
return E_NOINTERFACE;
}
ULONG
HandlerProvider::AddRef() { return ++mRefCnt; }
ULONG
HandlerProvider::Release() {
ULONG result = --mRefCnt;
if (!result) {
delete this;
}
return result;
}
HRESULT
HandlerProvider::GetHandler(NotNull<CLSID*> aHandlerClsid) {
if (!IsTargetInterfaceCacheable()) {
return E_NOINTERFACE;
}
*aHandlerClsid = CLSID_AccessibleHandler;
return S_OK;
}
void HandlerProvider::GetAndSerializePayload(
const MutexAutoLock&, NotNull<mscom::IInterceptor*> aInterceptor) {
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
if (mSerializer) {
return;
}
IA2PayloadPtr payload;
{ // Scope for lock
MutexAutoLock lock(mPayloadMutex);
if (mPayload) {
// The payload was already built by prebuildPayload() called during a
// bulk fetch operation.
payload = std::move(mPayload);
}
}
if (!payload) {
// We don't have a pre-built payload, so build it now.
payload.reset(new IA2Payload());
if (!mscom::InvokeOnMainThread(
"HandlerProvider::BuildInitialIA2Data", this,
&HandlerProvider::BuildInitialIA2Data,
std::forward<NotNull<mscom::IInterceptor*>>(aInterceptor),
std::forward<StaticIA2Data*>(&payload->mStaticData),
std::forward<DynamicIA2Data*>(&payload->mDynamicData)) ||
!payload->mDynamicData.mUniqueId) {
return;
}
}
// But we set mGeckoBackChannel on the current thread which resides in the
// MTA. This is important to ensure that COM always invokes
// IGeckoBackChannel methods in an MTA background thread.
RefPtr<IGeckoBackChannel> payloadRef(this);
// AddRef/Release pair for this reference is handled by payloadRef
payload->mGeckoBackChannel = this;
mSerializer = MakeUnique<mscom::StructToStream>(*payload, &IA2Payload_Encode);
}
HRESULT
HandlerProvider::GetHandlerPayloadSize(
NotNull<mscom::IInterceptor*> aInterceptor,
NotNull<DWORD*> aOutPayloadSize) {
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
if (!IsTargetInterfaceCacheable()) {
// No handler, so no payload for this instance.
return E_NOTIMPL;
}
MutexAutoLock lock(mMutex);
GetAndSerializePayload(lock, aInterceptor);
if (!mSerializer || !(*mSerializer)) {
// Failed payload serialization is non-fatal
*aOutPayloadSize = mscom::StructToStream::GetEmptySize();
return S_OK;
}
*aOutPayloadSize = mSerializer->GetSize();
return S_OK;
}
void HandlerProvider::BuildStaticIA2Data(
NotNull<mscom::IInterceptor*> aInterceptor, StaticIA2Data* aOutData) {
MOZ_ASSERT(aOutData);
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mTargetUnk);
MOZ_ASSERT(IsTargetInterfaceCacheable());
// Include interfaces the client is likely to request.
// This is cheap here and saves multiple cross-process calls later.
// These interfaces must be released in ReleaseStaticIA2DataInterfaces!
// If the target is already an IAccessible2, this pointer is redundant.
// However, the target might be an IAccessibleHyperlink, etc., in which
// case the client will almost certainly QI for IAccessible2.
HRESULT hr = aInterceptor->GetInterceptorForIID(NEWEST_IA2_IID,
(void**)&aOutData->mIA2);
if (FAILED(hr)) {
// IA2 should always be present, so something has
// gone very wrong if this fails.
aOutData->mIA2 = nullptr;
return;
}
// Some of these interfaces aren't present on all accessibles,
// so it's not a failure if these interfaces can't be fetched.
hr = aInterceptor->GetInterceptorForIID(IID_IAccessibleHypertext2,
(void**)&aOutData->mIAHypertext);
if (FAILED(hr)) {
aOutData->mIAHypertext = nullptr;
}
hr = aInterceptor->GetInterceptorForIID(IID_IAccessibleHyperlink,
(void**)&aOutData->mIAHyperlink);
if (FAILED(hr)) {
aOutData->mIAHyperlink = nullptr;
}
hr = aInterceptor->GetInterceptorForIID(IID_IAccessibleTable,
(void**)&aOutData->mIATable);
if (FAILED(hr)) {
aOutData->mIATable = nullptr;
}
hr = aInterceptor->GetInterceptorForIID(IID_IAccessibleTable2,
(void**)&aOutData->mIATable2);
if (FAILED(hr)) {
aOutData->mIATable2 = nullptr;
}
hr = aInterceptor->GetInterceptorForIID(IID_IAccessibleTableCell,
(void**)&aOutData->mIATableCell);
if (FAILED(hr)) {
aOutData->mIATableCell = nullptr;
}
}
void HandlerProvider::BuildDynamicIA2Data(DynamicIA2Data* aOutIA2Data,
bool aMarshaledByCom) {
MOZ_ASSERT(aOutIA2Data);
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsTargetInterfaceCacheable());
if (!mTargetUnk) {
return;
}
RefPtr<NEWEST_IA2_INTERFACE> target;
HRESULT hr =
mTargetUnk.get()->QueryInterface(NEWEST_IA2_IID, getter_AddRefs(target));
if (FAILED(hr)) {
return;
}
hr = E_UNEXPECTED;
auto hasFailed = [&hr]() -> bool { return FAILED(hr); };
auto cleanup = [aOutIA2Data, aMarshaledByCom]() -> void {
CleanupDynamicIA2Data(*aOutIA2Data, aMarshaledByCom);
};
mscom::ExecuteWhen<decltype(hasFailed), decltype(cleanup)> onFail(hasFailed,
cleanup);
// When allocating memory to be returned to the client, you *must* use
// allocMem, not CoTaskMemAlloc!
auto allocMem = [aMarshaledByCom](size_t aSize) {
if (aMarshaledByCom) {
return ::CoTaskMemAlloc(aSize);
}
// We use midl_user_allocate rather than CoTaskMemAlloc because this
// struct is being marshaled by RPC, not COM.
return ::midl_user_allocate(aSize);
};
const VARIANT kChildIdSelf = {VT_I4};
VARIANT varVal;
hr = target->accLocation(&aOutIA2Data->mLeft, &aOutIA2Data->mTop,
&aOutIA2Data->mWidth, &aOutIA2Data->mHeight,
kChildIdSelf);
if (FAILED(hr)) {
return;
}
hr = target->get_accRole(kChildIdSelf, &aOutIA2Data->mRole);
if (FAILED(hr)) {
return;
}
hr = target->get_accState(kChildIdSelf, &varVal);
if (FAILED(hr)) {
return;
}
aOutIA2Data->mState = varVal.lVal;
hr = target->get_accKeyboardShortcut(kChildIdSelf,
&aOutIA2Data->mKeyboardShortcut);
if (FAILED(hr)) {
return;
}
hr = target->get_accName(kChildIdSelf, &aOutIA2Data->mName);
if (FAILED(hr)) {
return;
}
hr = target->get_accDescription(kChildIdSelf, &aOutIA2Data->mDescription);
if (FAILED(hr)) {
return;
}
hr = target->get_accDefaultAction(kChildIdSelf, &aOutIA2Data->mDefaultAction);
if (FAILED(hr)) {
return;
}
hr = target->get_accChildCount(&aOutIA2Data->mChildCount);
if (FAILED(hr)) {
return;
}
hr = target->get_accValue(kChildIdSelf, &aOutIA2Data->mValue);
if (FAILED(hr)) {
return;
}
hr = target->get_states(&aOutIA2Data->mIA2States);
if (FAILED(hr)) {
return;
}
hr = target->get_attributes(&aOutIA2Data->mAttributes);
if (FAILED(hr)) {
return;
}
HWND hwnd;
hr = target->get_windowHandle(&hwnd);
if (FAILED(hr)) {
return;
}
aOutIA2Data->mHwnd = PtrToLong(hwnd);
hr = target->get_locale(&aOutIA2Data->mIA2Locale);
if (FAILED(hr)) {
return;
}
hr = target->role(&aOutIA2Data->mIA2Role);
if (FAILED(hr)) {
return;
}
RefPtr<IAccessibleAction> action;
// It is not an error if this fails.
hr = mTargetUnk.get()->QueryInterface(IID_IAccessibleAction,
getter_AddRefs(action));
if (SUCCEEDED(hr)) {
hr = action->nActions(&aOutIA2Data->mNActions);
if (FAILED(hr)) {
return;
}
}
RefPtr<IAccessibleTableCell> cell;
// It is not an error if this fails.
hr = mTargetUnk.get()->QueryInterface(IID_IAccessibleTableCell,
getter_AddRefs(cell));
if (SUCCEEDED(hr)) {
hr = cell->get_rowColumnExtents(
&aOutIA2Data->mRowIndex, &aOutIA2Data->mColumnIndex,
&aOutIA2Data->mRowExtent, &aOutIA2Data->mColumnExtent,
&aOutIA2Data->mCellIsSelected);
if (FAILED(hr)) {
return;
}
// Because the same headers can apply to many cells, include the ids of
// header cells, rather than the actual objects. Otherwise, we might
// end up marshaling the same objects (and their payloads) many times.
IUnknown** headers = nullptr;
hr = cell->get_rowHeaderCells(&headers, &aOutIA2Data->mNRowHeaderCells);
if (FAILED(hr)) {
return;
}
if (aOutIA2Data->mNRowHeaderCells > 0) {
aOutIA2Data->mRowHeaderCellIds = static_cast<long*>(
allocMem(sizeof(long) * aOutIA2Data->mNRowHeaderCells));
for (long i = 0; i < aOutIA2Data->mNRowHeaderCells; ++i) {
RefPtr<IAccessible2> headerAcc;
hr = headers[i]->QueryInterface(IID_IAccessible2,
getter_AddRefs(headerAcc));
MOZ_ASSERT(SUCCEEDED(hr));
headers[i]->Release();
hr = headerAcc->get_uniqueID(&aOutIA2Data->mRowHeaderCellIds[i]);
MOZ_ASSERT(SUCCEEDED(hr));
}
}
::CoTaskMemFree(headers);
hr = cell->get_columnHeaderCells(&headers,
&aOutIA2Data->mNColumnHeaderCells);
if (FAILED(hr)) {
return;
}
if (aOutIA2Data->mNColumnHeaderCells > 0) {
aOutIA2Data->mColumnHeaderCellIds = static_cast<long*>(
allocMem(sizeof(long) * aOutIA2Data->mNColumnHeaderCells));
for (long i = 0; i < aOutIA2Data->mNColumnHeaderCells; ++i) {
RefPtr<IAccessible2> headerAcc;
hr = headers[i]->QueryInterface(IID_IAccessible2,
getter_AddRefs(headerAcc));
MOZ_ASSERT(SUCCEEDED(hr));
headers[i]->Release();
hr = headerAcc->get_uniqueID(&aOutIA2Data->mColumnHeaderCellIds[i]);
MOZ_ASSERT(SUCCEEDED(hr));
}
}
::CoTaskMemFree(headers);
}
// NB: get_uniqueID should be the final property retrieved in this method,
// as its presence is used to determine whether the rest of this data
// retrieval was successful.
hr = target->get_uniqueID(&aOutIA2Data->mUniqueId);
}
void HandlerProvider::BuildInitialIA2Data(
NotNull<mscom::IInterceptor*> aInterceptor, StaticIA2Data* aOutStaticData,
DynamicIA2Data* aOutDynamicData) {
BuildStaticIA2Data(aInterceptor, aOutStaticData);
if (!aOutStaticData->mIA2) {
return;
}
BuildDynamicIA2Data(aOutDynamicData);
}
bool HandlerProvider::IsTargetInterfaceCacheable() {
return MarshalAs(mTargetUnkIid) == NEWEST_IA2_IID ||
mTargetUnkIid == IID_IAccessibleHyperlink;
}
HRESULT
HandlerProvider::WriteHandlerPayload(NotNull<mscom::IInterceptor*> aInterceptor,
NotNull<IStream*> aStream) {
if (!IsTargetInterfaceCacheable()) {
// No handler, so no payload for this instance.
return E_NOTIMPL;
}
MutexAutoLock lock(mMutex);
if (!mSerializer || !(*mSerializer)) {
// Failed payload serialization is non-fatal
mscom::StructToStream emptyStruct;
return emptyStruct.Write(aStream);
}
HRESULT hr = mSerializer->Write(aStream);
mSerializer.reset();
return hr;
}
REFIID
HandlerProvider::MarshalAs(REFIID aIid) {
static_assert(&NEWEST_IA2_IID == &IID_IAccessible2_3,
"You have modified NEWEST_IA2_IID. This code needs updating.");
if (aIid == IID_IDispatch || aIid == IID_IAccessible ||
aIid == IID_IAccessible2 || aIid == IID_IAccessible2_2 ||
aIid == IID_IAccessible2_3) {
// This should always be the newest IA2 interface ID
return NEWEST_IA2_IID;
}
// Otherwise we juse return the identity.
return aIid;
}
HRESULT
HandlerProvider::DisconnectHandlerRemotes() {
// If a handlerProvider call is pending on another thread,
// CoDisconnectObject won't release this HandlerProvider immediately.
// However, the interceptor and its target (mTargetUnk) might be destroyed.
mTargetUnk = nullptr;
IUnknown* unk = static_cast<IGeckoBackChannel*>(this);
return ::CoDisconnectObject(unk, 0);
}
HRESULT
HandlerProvider::IsInterfaceMaybeSupported(REFIID aIid) {
static_assert(&NEWEST_IA2_IID == &IID_IAccessible2_3,
"You have modified NEWEST_IA2_IID. This code needs updating.");
if (aIid == IID_IUnknown || aIid == IID_IDispatch ||
aIid == IID_IAccessible || aIid == IID_IServiceProvider ||
aIid == IID_IEnumVARIANT || aIid == IID_IAccessible2 ||
aIid == IID_IAccessible2_2 || aIid == IID_IAccessible2_3 ||
aIid == IID_IAccessibleAction || aIid == IID_IAccessibleApplication ||
aIid == IID_IAccessibleComponent || aIid == IID_IAccessibleDocument ||
aIid == IID_IAccessibleEditableText || aIid == IID_IAccessibleHyperlink ||
aIid == IID_IAccessibleHypertext || aIid == IID_IAccessibleHypertext2 ||
aIid == IID_IAccessibleImage || aIid == IID_IAccessibleRelation ||
aIid == IID_IAccessibleTable || aIid == IID_IAccessibleTable2 ||
aIid == IID_IAccessibleTableCell || aIid == IID_IAccessibleText ||
aIid == IID_IAccessibleValue || aIid == IID_ISimpleDOMNode ||
aIid == IID_ISimpleDOMDocument || aIid == IID_ISimpleDOMText ||
aIid == IID_IAccessibleEx || aIid == IID_IRawElementProviderSimple) {
return S_OK;
}
return E_NOINTERFACE;
}
REFIID
HandlerProvider::GetEffectiveOutParamIid(REFIID aCallIid, ULONG aCallMethod) {
if (aCallIid == IID_IAccessibleTable || aCallIid == IID_IAccessibleTable2 ||
aCallIid == IID_IAccessibleDocument ||
aCallIid == IID_IAccessibleTableCell ||
aCallIid == IID_IAccessibleRelation) {
return NEWEST_IA2_IID;
}
// IAccessible2_2::accessibleWithCaret
static_assert(&NEWEST_IA2_IID == &IID_IAccessible2_3,
"You have modified NEWEST_IA2_IID. This code needs updating.");
if ((aCallIid == IID_IAccessible2_2 || aCallIid == IID_IAccessible2_3) &&
aCallMethod == 47) {
return NEWEST_IA2_IID;
}
// IAccessible::get_accSelection
if ((aCallIid == IID_IAccessible || aCallIid == IID_IAccessible2 ||
aCallIid == IID_IAccessible2_2 || aCallIid == IID_IAccessible2_3) &&
aCallMethod == 19) {
return IID_IEnumVARIANT;
}
MOZ_ASSERT(false);
return IID_IUnknown;
}
HRESULT
HandlerProvider::NewInstance(
REFIID aIid, mscom::InterceptorTargetPtr<IUnknown> aTarget,
NotNull<mscom::IHandlerProvider**> aOutNewPayload) {
RefPtr<IHandlerProvider> newPayload(
new HandlerProvider(aIid, std::move(aTarget)));
newPayload.forget(aOutNewPayload.get());
return S_OK;
}
void HandlerProvider::SetHandlerControlOnMainThread(
DWORD aPid, mscom::ProxyUniquePtr<IHandlerControl> aCtrl) {
MOZ_ASSERT(NS_IsMainThread());
// XXX This is no longer used and will soon be removed.
}
HRESULT
HandlerProvider::put_HandlerControl(long aPid, IHandlerControl* aCtrl) {
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
if (!aCtrl) {
return E_INVALIDARG;
}
auto ptrProxy = mscom::ToProxyUniquePtr(aCtrl);
if (!mscom::InvokeOnMainThread(
"HandlerProvider::SetHandlerControlOnMainThread", this,
&HandlerProvider::SetHandlerControlOnMainThread,
static_cast<DWORD>(aPid), std::move(ptrProxy))) {
return E_FAIL;
}
return S_OK;
}
HRESULT
HandlerProvider::Refresh(DynamicIA2Data* aOutData) {
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
if (!mTargetUnk) {
return CO_E_OBJNOTCONNECTED;
}
if (!mscom::InvokeOnMainThread("HandlerProvider::BuildDynamicIA2Data", this,
&HandlerProvider::BuildDynamicIA2Data,
std::forward<DynamicIA2Data*>(aOutData),
/* aMarshaledByCom */ true)) {
return E_FAIL;
}
if (!aOutData->mUniqueId) {
// BuildDynamicIA2Data failed.
if (!mTargetUnk) {
// Even though we checked this before, the accessible can be shut down
// before BuildDynamicIA2Data executes on the main thread.
return CO_E_OBJNOTCONNECTED;
}
return E_FAIL;
}
return S_OK;
}
void HandlerProvider::PrebuildPayload(
NotNull<mscom::IInterceptor*> aInterceptor) {
MOZ_ASSERT(NS_IsMainThread());
MutexAutoLock lock(mPayloadMutex);
mPayload.reset(new IA2Payload());
BuildInitialIA2Data(aInterceptor, &mPayload->mStaticData,
&mPayload->mDynamicData);
if (!mPayload->mDynamicData.mUniqueId) {
// Building the payload failed.
mPayload.reset();
}
}
template <typename Interface>
HRESULT HandlerProvider::ToWrappedObject(Interface** aObj) {
MOZ_ASSERT(NS_IsMainThread());
mscom::STAUniquePtr<Interface> inObj(*aObj);
RefPtr<HandlerProvider> hprov = new HandlerProvider(
__uuidof(Interface), mscom::ToInterceptorTargetPtr(inObj));
HRESULT hr =
mscom::MainThreadHandoff::WrapInterface(std::move(inObj), hprov, aObj);
if (FAILED(hr)) {
*aObj = nullptr;
return hr;
}
// Build the payload for this object now to avoid a cross-thread call when
// marshaling it later.
RefPtr<mscom::IInterceptor> interceptor;
hr = (*aObj)->QueryInterface(mscom::IID_IInterceptor,
getter_AddRefs(interceptor));
MOZ_ASSERT(SUCCEEDED(hr));
// Even though we created a new HandlerProvider, that won't be used if
// there's an existing Interceptor. Therefore, we must get the
// HandlerProvider from the Interceptor.
RefPtr<mscom::IInterceptorSink> interceptorSink;
interceptor->GetEventSink(getter_AddRefs(interceptorSink));
MOZ_ASSERT(interceptorSink);
RefPtr<mscom::IMainThreadHandoff> handoff;
hr = interceptorSink->QueryInterface(mscom::IID_IMainThreadHandoff,
getter_AddRefs(handoff));
// If a11y Interceptors stop using MainThreadHandoff as their event sink, we
// *really* want to know about it ASAP.
MOZ_DIAGNOSTIC_ASSERT(SUCCEEDED(hr),
"A11y Interceptor isn't using MainThreadHandoff");
RefPtr<mscom::IHandlerProvider> usedIHprov;
handoff->GetHandlerProvider(getter_AddRefs(usedIHprov));
MOZ_ASSERT(usedIHprov);
auto usedHprov = static_cast<HandlerProvider*>(usedIHprov.get());
usedHprov->PrebuildPayload(WrapNotNull(interceptor));
return hr;
}
void HandlerProvider::GetAllTextInfoMainThread(
BSTR* aText, IAccessibleHyperlink*** aHyperlinks, long* aNHyperlinks,
IA2TextSegment** aAttribRuns, long* aNAttribRuns, HRESULT* result) {
MOZ_ASSERT(aText);
MOZ_ASSERT(aHyperlinks);
MOZ_ASSERT(aNHyperlinks);
MOZ_ASSERT(aAttribRuns);
MOZ_ASSERT(aNAttribRuns);
MOZ_ASSERT(NS_IsMainThread());
if (!mTargetUnk) {
*result = CO_E_OBJNOTCONNECTED;
return;
}
RefPtr<IAccessibleHypertext2> ht;
HRESULT hr =
mTargetUnk->QueryInterface(IID_IAccessibleHypertext2, getter_AddRefs(ht));
if (FAILED(hr)) {
*result = hr;
return;
}
hr = ht->get_text(0, IA2_TEXT_OFFSET_LENGTH, aText);
if (FAILED(hr)) {
*result = hr;
return;
}
if (hr == S_FALSE) {
// No text.
*aHyperlinks = nullptr;
*aNHyperlinks = 0;
*aAttribRuns = nullptr;
*aNAttribRuns = 0;
*result = S_FALSE;
return;
}
hr = ht->get_hyperlinks(aHyperlinks, aNHyperlinks);
if (FAILED(hr)) {
*aHyperlinks = nullptr;
// -1 signals to the handler that it should call hyperlinks itself.
*aNHyperlinks = -1;
}
// We must wrap these hyperlinks in an interceptor.
for (long index = 0; index < *aNHyperlinks; ++index) {
ToWrappedObject(&(*aHyperlinks)[index]);
}
// Fetch all attribute runs.
nsTArray<IA2TextSegment> attribRuns;
long end = 0;
long length = ::SysStringLen(*aText);
while (end < length) {
long offset = end;
long start;
BSTR attribs;
// The (exclusive) end of the last run is the start of the next run.
hr = ht->get_attributes(offset, &start, &end, &attribs);
// Bug 1421873: Gecko can return end <= offset in some rare cases, which
// isn't valid. This is perhaps because the text mutated during the loop
// for some reason, making this offset invalid.
if (FAILED(hr) || end <= offset) {
break;
}
attribRuns.AppendElement(IA2TextSegment({attribs, start, end}));
}
// Put the attribute runs in a COM array.
*aNAttribRuns = attribRuns.Length();
*aAttribRuns = static_cast<IA2TextSegment*>(
::CoTaskMemAlloc(sizeof(IA2TextSegment) * *aNAttribRuns));
for (long index = 0; index < *aNAttribRuns; ++index) {
(*aAttribRuns)[index] = attribRuns[index];
}
*result = S_OK;
}
HRESULT
HandlerProvider::get_AllTextInfo(BSTR* aText,
IAccessibleHyperlink*** aHyperlinks,
long* aNHyperlinks,
IA2TextSegment** aAttribRuns,
long* aNAttribRuns) {
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
if (!mTargetUnk) {
return CO_E_OBJNOTCONNECTED;
}
HRESULT hr;
if (!mscom::InvokeOnMainThread(
"HandlerProvider::GetAllTextInfoMainThread", this,
&HandlerProvider::GetAllTextInfoMainThread,
std::forward<BSTR*>(aText),
std::forward<IAccessibleHyperlink***>(aHyperlinks),
std::forward<long*>(aNHyperlinks),
std::forward<IA2TextSegment**>(aAttribRuns),
std::forward<long*>(aNAttribRuns), std::forward<HRESULT*>(&hr))) {
return E_FAIL;
}
return hr;
}
void HandlerProvider::GetRelationsInfoMainThread(IARelationData** aRelations,
long* aNRelations,
HRESULT* hr) {
MOZ_ASSERT(aRelations);
MOZ_ASSERT(aNRelations);
MOZ_ASSERT(NS_IsMainThread());
if (!mTargetUnk) {
*hr = CO_E_OBJNOTCONNECTED;
return;
}
RefPtr<NEWEST_IA2_INTERFACE> acc;
*hr = mTargetUnk.get()->QueryInterface(NEWEST_IA2_IID, getter_AddRefs(acc));
if (FAILED(*hr)) {
return;
}
*hr = acc->get_nRelations(aNRelations);
if (FAILED(*hr)) {
return;
}
auto rawRels = MakeUnique<IAccessibleRelation*[]>(*aNRelations);
*hr = acc->get_relations(*aNRelations, rawRels.get(), aNRelations);
if (FAILED(*hr)) {
return;
}
*aRelations = static_cast<IARelationData*>(
::CoTaskMemAlloc(sizeof(IARelationData) * *aNRelations));
for (long index = 0; index < *aNRelations; ++index) {
IAccessibleRelation* rawRel = rawRels[index];
IARelationData& relData = (*aRelations)[index];
*hr = rawRel->get_relationType(&relData.mType);
if (FAILED(*hr)) {
relData.mType = nullptr;
}
*hr = rawRel->get_nTargets(&relData.mNTargets);
if (FAILED(*hr)) {
relData.mNTargets = -1;
}
rawRel->Release();
}
*hr = S_OK;
}
HRESULT
HandlerProvider::get_RelationsInfo(IARelationData** aRelations,
long* aNRelations) {
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
if (!mTargetUnk) {
return CO_E_OBJNOTCONNECTED;
}
HRESULT hr;
if (!mscom::InvokeOnMainThread(
"HandlerProvider::GetRelationsInfoMainThread", this,
&HandlerProvider::GetRelationsInfoMainThread,
std::forward<IARelationData**>(aRelations),
std::forward<long*>(aNRelations), std::forward<HRESULT*>(&hr))) {
return E_FAIL;
}
return hr;
}
// Helper function for GetAllChildrenMainThread.
static bool SetChildDataForTextLeaf(NEWEST_IA2_INTERFACE* acc,
AccChildData& data) {
const VARIANT kChildIdSelf = {VT_I4};
VARIANT varVal;
// 1. Check whether this is a text leaf.
// 1.1. A text leaf always has ROLE_SYSTEM_TEXT or ROLE_SYSTEM_WHITESPACE.
HRESULT hr = acc->get_accRole(kChildIdSelf, &varVal);
if (FAILED(hr)) {
return false;
}
if (varVal.vt != VT_I4) {
return false;
}
long role = varVal.lVal;
if (role != ROLE_SYSTEM_TEXT && role != ROLE_SYSTEM_WHITESPACE) {
return false;
}
// 1.2. A text leaf doesn't support IAccessibleText.
RefPtr<IAccessibleText> iaText;
hr = acc->QueryInterface(IID_IAccessibleText, getter_AddRefs(iaText));
if (SUCCEEDED(hr)) {
return false;
}
// 1.3. A text leaf doesn't have children.
long count;
hr = acc->get_accChildCount(&count);
if (FAILED(hr) || count != 0) {
return false;
}
// 2. Update |data| with the data for this text leaf.
// Because marshaling objects is more expensive than marshaling other data,
// we just marshal the data we need for text leaf children, rather than
// marshaling the full accessible object.
// |data| has already been zeroed, so we don't need to do anything if these
// calls fail.
acc->get_accName(kChildIdSelf, &data.mText);
data.mTextRole = role;
acc->get_uniqueID(&data.mTextId);
acc->get_accState(kChildIdSelf, &varVal);
data.mTextState = varVal.lVal;
acc->accLocation(&data.mTextLeft, &data.mTextTop, &data.mTextWidth,
&data.mTextHeight, kChildIdSelf);
return true;
}
void HandlerProvider::GetAllChildrenMainThread(AccChildData** aChildren,
ULONG* aNChildren, HRESULT* hr) {
MOZ_ASSERT(aChildren);
MOZ_ASSERT(aNChildren);
MOZ_ASSERT(NS_IsMainThread());
if (!mTargetUnk) {
*hr = CO_E_OBJNOTCONNECTED;
return;
}
RefPtr<NEWEST_IA2_INTERFACE> acc;
*hr = mTargetUnk.get()->QueryInterface(NEWEST_IA2_IID, getter_AddRefs(acc));
if (FAILED(*hr)) {
return;
}
long count;
*hr = acc->get_accChildCount(&count);
if (FAILED(*hr)) {
return;
}
MOZ_ASSERT(count >= 0);
if (count == 0) {
*aChildren = nullptr;
*aNChildren = 0;
return;
}
RefPtr<IEnumVARIANT> enumVar;
*hr = mTargetUnk.get()->QueryInterface(IID_IEnumVARIANT,
getter_AddRefs(enumVar));
if (FAILED(*hr)) {
return;
}
auto rawChildren = MakeUnique<VARIANT[]>(count);
*hr = enumVar->Next((ULONG)count, rawChildren.get(), aNChildren);
if (FAILED(*hr)) {
*aChildren = nullptr;
*aNChildren = 0;
return;
}
*aChildren = static_cast<AccChildData*>(
::CoTaskMemAlloc(sizeof(AccChildData) * *aNChildren));
for (ULONG index = 0; index < *aNChildren; ++index) {
(*aChildren)[index] = {};
AccChildData& child = (*aChildren)[index];
MOZ_ASSERT(rawChildren[index].vt == VT_DISPATCH);
MOZ_ASSERT(rawChildren[index].pdispVal);
RefPtr<NEWEST_IA2_INTERFACE> childAcc;
*hr = rawChildren[index].pdispVal->QueryInterface(NEWEST_IA2_IID,
getter_AddRefs(childAcc));
rawChildren[index].pdispVal->Release();
MOZ_ASSERT(SUCCEEDED(*hr));
if (FAILED(*hr)) {
continue;
}
if (!SetChildDataForTextLeaf(childAcc, child)) {
// This isn't a text leaf. Marshal the accessible.
childAcc.forget(&child.mAccessible);
// We must wrap this accessible in an Interceptor.
ToWrappedObject(&child.mAccessible);
}
}
*hr = S_OK;
}
HRESULT
HandlerProvider::get_AllChildren(AccChildData** aChildren, ULONG* aNChildren) {
MOZ_ASSERT(mscom::IsCurrentThreadMTA());
HRESULT hr;
if (!mscom::InvokeOnMainThread(
"HandlerProvider::GetAllChildrenMainThread", this,
&HandlerProvider::GetAllChildrenMainThread,
std::forward<AccChildData**>(aChildren),
std::forward<ULONG*>(aNChildren), std::forward<HRESULT*>(&hr))) {
return E_FAIL;
}
return hr;
}
} // namespace a11y
} // namespace mozilla

View File

@ -1,145 +0,0 @@
/* -*- 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/. */
#ifndef mozilla_a11y_HandlerProvider_h
#define mozilla_a11y_HandlerProvider_h
#include "mozilla/a11y/AccessibleHandler.h"
#include "mozilla/a11y/HandlerDataCleanup.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/Atomics.h"
#include "mozilla/mscom/IHandlerProvider.h"
#include "mozilla/mscom/Ptr.h"
#include "mozilla/mscom/StructStream.h"
#include "mozilla/Mutex.h"
#include "mozilla/UniquePtr.h"
#include "HandlerData.h"
struct NEWEST_IA2_INTERFACE;
namespace mozilla {
namespace mscom {
class StructToStream;
} // namespace mscom
namespace a11y {
class HandlerProvider final : public IGeckoBackChannel,
public mscom::IHandlerProvider {
public:
HandlerProvider(REFIID aIid, mscom::InterceptorTargetPtr<IUnknown> aTarget);
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
// IHandlerProvider
STDMETHODIMP GetHandler(NotNull<CLSID*> aHandlerClsid) override;
STDMETHODIMP GetHandlerPayloadSize(NotNull<mscom::IInterceptor*> aInterceptor,
NotNull<DWORD*> aOutPayloadSize) override;
STDMETHODIMP WriteHandlerPayload(NotNull<mscom::IInterceptor*> aInterceptor,
NotNull<IStream*> aStream) override;
STDMETHODIMP_(REFIID) MarshalAs(REFIID aIid) override;
STDMETHODIMP DisconnectHandlerRemotes() override;
STDMETHODIMP IsInterfaceMaybeSupported(REFIID aIid) override;
STDMETHODIMP_(REFIID)
GetEffectiveOutParamIid(REFIID aCallIid, ULONG aCallMethod) override;
STDMETHODIMP NewInstance(
REFIID aIid, mscom::InterceptorTargetPtr<IUnknown> aTarget,
NotNull<mscom::IHandlerProvider**> aOutNewPayload) override;
// IGeckoBackChannel
STDMETHODIMP put_HandlerControl(long aPid, IHandlerControl* aCtrl) override;
STDMETHODIMP Refresh(DynamicIA2Data* aOutData) override;
STDMETHODIMP get_AllTextInfo(BSTR* aText, IAccessibleHyperlink*** aHyperlinks,
long* aNHyperlinks, IA2TextSegment** aAttribRuns,
long* aNAttribRuns) override;
STDMETHODIMP get_RelationsInfo(IARelationData** aRelations,
long* aNRelations) override;
STDMETHODIMP get_AllChildren(AccChildData** aChildren,
ULONG* aNChildren) override;
private:
~HandlerProvider() = default;
void SetHandlerControlOnMainThread(
DWORD aPid, mscom::ProxyUniquePtr<IHandlerControl> aCtrl);
void GetAndSerializePayload(const MutexAutoLock&,
NotNull<mscom::IInterceptor*> aInterceptor);
void BuildStaticIA2Data(NotNull<mscom::IInterceptor*> aInterceptor,
StaticIA2Data* aOutData);
/**
* Pass true for aMarshaledByCom if this struct is being directly marshaled as
* an out parameter of a COM method, currently only
* IGeckoBackChannel::Refresh.
* When aMarshaledByCom is false, this means the struct is being marshaled
* by RPC encoding functions. This means we must allocate memory differently,
* even though we're using this as part of a COM handler payload.
*/
void BuildDynamicIA2Data(DynamicIA2Data* aOutIA2Data,
bool aMarshaledByCom = false);
void BuildInitialIA2Data(NotNull<mscom::IInterceptor*> aInterceptor,
StaticIA2Data* aOutStaticData,
DynamicIA2Data* aOutDynamicData);
bool IsTargetInterfaceCacheable();
/**
* Build the payload for later marshaling.
* This is intended to be used during a bulk fetch operation and must only be
* called from the main thread.
*/
void PrebuildPayload(NotNull<mscom::IInterceptor*> aInterceptor);
// Replace a raw object from the main thread with a wrapped, intercepted
// object suitable for calling from the MTA.
// The reference to the original object is adopted; i.e. you should not
// separately release it.
// This is intended for objects returned from method calls on the main thread.
template <typename Interface>
HRESULT ToWrappedObject(Interface** aObj);
void GetAllTextInfoMainThread(BSTR* aText,
IAccessibleHyperlink*** aHyperlinks,
long* aNHyperlinks,
IA2TextSegment** aAttribRuns,
long* aNAttribRuns, HRESULT* result);
void GetRelationsInfoMainThread(IARelationData** aRelations,
long* aNRelations, HRESULT* result);
void GetAllChildrenMainThread(AccChildData** aChildren, ULONG* aNChildren,
HRESULT* result);
Atomic<uint32_t> mRefCnt;
Mutex mMutex MOZ_UNANNOTATED; // Protects mSerializer
const IID mTargetUnkIid;
mscom::InterceptorTargetPtr<IUnknown>
mTargetUnk; // Constant, main thread only
UniquePtr<mscom::StructToStream> mSerializer;
RefPtr<IUnknown> mFastMarshalUnk;
struct IA2PayloadDeleter {
void operator()(IA2Payload* aPayload) {
// When CoMarshalInterface writes interfaces out to a stream, it AddRefs.
// Therefore, we must release our references after this.
ReleaseStaticIA2DataInterfaces(aPayload->mStaticData);
CleanupDynamicIA2Data(aPayload->mDynamicData);
delete aPayload;
}
};
using IA2PayloadPtr = UniquePtr<IA2Payload, IA2PayloadDeleter>;
// Used when the payload is built prior to marshaling the object by a bulk
// fetch operation. See prebuildPayload().
IA2PayloadPtr mPayload;
Mutex mPayloadMutex MOZ_UNANNOTATED; // Protects mPayload
};
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_HandlerProvider_h

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
;+# 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/.
LIBRARY AccessibleHandler.dll
EXPORTS DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
GetProxyDllInfo PRIVATE
RegisterMsix PRIVATE

View File

@ -1,336 +0,0 @@
/* -*- 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/. */
#ifndef mozilla_a11y_AccessibleHandler_h
#define mozilla_a11y_AccessibleHandler_h
#define NEWEST_IA2_BASENAME Accessible2_3
#define __GENIFACE(base) I##base
#define INTERFACEFOR(base) __GENIFACE(base)
#define NEWEST_IA2_INTERFACE INTERFACEFOR(NEWEST_IA2_BASENAME)
#define __GENIID(iface) IID_##iface
#define IIDFOR(iface) __GENIID(iface)
#define NEWEST_IA2_IID IIDFOR(NEWEST_IA2_INTERFACE)
#if defined(__midl) || defined(__WIDL__)
import "Accessible2_3.idl";
#else
# include "HandlerData.h"
# include <windows.h>
namespace mozilla {
namespace a11y {
static const GUID kUnsupportedServices[] = {
// clang-format off
// Unknown, queried by Windows on devices with touch screens or similar devices
// connected.
{0x33f139ee, 0xe509, 0x47f7, {0xbf, 0x39, 0x83, 0x76, 0x44, 0xf7, 0x45, 0x76}},
// Unknown, queried by Windows
{0xFDA075CF, 0x7C8B, 0x498C, { 0xB5, 0x14, 0xA9, 0xCB, 0x52, 0x1B, 0xBF, 0xB4 }},
// 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 }},
// SID_IsUIAutomationObject (undocumented), queried by Windows
{0xb96fdb85, 0x7204, 0x4724, { 0x84, 0x2b, 0xc7, 0x05, 0x9d, 0xed, 0xb9, 0xd0 }},
// IIS_IsOleaccProxy (undocumented), queried by Windows
{0x902697FA, 0x80E4, 0x4560, {0x80, 0x2A, 0xA1, 0x3F, 0x22, 0xA6, 0x47, 0x09}},
// IID_IHTMLElement, queried by JAWS
{0x3050F1FF, 0x98B5, 0x11CF, {0xBB, 0x82, 0x00, 0xAA, 0x00, 0xBD, 0xCE, 0x0B}}
// clang-format on
};
}
} // namespace mozilla
# if !defined(MOZILLA_INTERNAL_API)
# include "Accessible2_3.h"
# include "AccessibleHyperlink.h"
# include "AccessibleHypertext2.h"
# include "AccessibleTableCell.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 IAccessibleTableCell,
public IAccessibleHypertext2 {
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;
REFIID MarshalAs(REFIID aRequestedIid) override;
HRESULT GetMarshalInterface(REFIID aMarshalAsIid, NotNull<IUnknown*> aProxy,
NotNull<IID*> aOutIid,
NotNull<IUnknown**> aOutUnk) override;
HRESULT GetHandlerPayloadSize(REFIID aIid, DWORD* aOutPayloadSize) override;
HRESULT WriteHandlerPayload(IStream* aStream, REFIID aIId) override;
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
// IDispatch
STDMETHODIMP GetTypeInfoCount(UINT* pctinfo) override;
STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid,
ITypeInfo** ppTInfo) override;
STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgDispId) override;
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS* pDispParams, VARIANT* pVarResult,
EXCEPINFO* pExcepInfo, UINT* puArgErr) override;
// IAccessible
STDMETHODIMP get_accParent(IDispatch** ppdispParent) override;
STDMETHODIMP get_accChildCount(long* pcountChildren) override;
STDMETHODIMP get_accChild(VARIANT varChild, IDispatch** ppdispChild) override;
STDMETHODIMP get_accName(VARIANT varChild, BSTR* pszName) override;
STDMETHODIMP get_accValue(VARIANT varChild, BSTR* pszValue) override;
STDMETHODIMP get_accDescription(VARIANT varChild,
BSTR* pszDescription) override;
STDMETHODIMP get_accRole(VARIANT varChild, VARIANT* pvarRole) override;
STDMETHODIMP get_accState(VARIANT varChild, VARIANT* pvarState) override;
STDMETHODIMP get_accHelp(VARIANT varChild, BSTR* pszHelp) override;
STDMETHODIMP get_accHelpTopic(BSTR* pszHelpFile, VARIANT varChild,
long* pidTopic) override;
STDMETHODIMP get_accKeyboardShortcut(VARIANT varChild,
BSTR* pszKeyboardShortcut) override;
STDMETHODIMP get_accFocus(VARIANT* pvarChild) override;
STDMETHODIMP get_accSelection(VARIANT* pvarChildren) override;
STDMETHODIMP get_accDefaultAction(VARIANT varChild,
BSTR* pszDefaultAction) override;
STDMETHODIMP accSelect(long flagsSelect, VARIANT varChild) override;
STDMETHODIMP accLocation(long* pxLeft, long* pyTop, long* pcxWidth,
long* pcyHeight, VARIANT varChild) override;
STDMETHODIMP accNavigate(long navDir, VARIANT varStart,
VARIANT* pvarEndUpAt) override;
STDMETHODIMP accHitTest(long xLeft, long yTop, VARIANT* pvarChild) override;
STDMETHODIMP accDoDefaultAction(VARIANT varChild) override;
STDMETHODIMP put_accName(VARIANT varChild, BSTR szName) override;
STDMETHODIMP put_accValue(VARIANT varChild, BSTR szValue) override;
// IAccessible2
STDMETHODIMP get_nRelations(long* nRelations) override;
STDMETHODIMP get_relation(long relationIndex,
IAccessibleRelation** relation) override;
STDMETHODIMP get_relations(long maxRelations, IAccessibleRelation** relations,
long* nRelations) override;
STDMETHODIMP role(long* role) override;
STDMETHODIMP scrollTo(IA2ScrollType scrollType) override;
STDMETHODIMP scrollToPoint(IA2CoordinateType coordinateType, long x,
long y) override;
STDMETHODIMP get_groupPosition(long* groupLevel, long* similarItemsInGroup,
long* positionInGroup) override;
STDMETHODIMP get_states(AccessibleStates* states) override;
STDMETHODIMP get_extendedRole(BSTR* extendedRole) override;
STDMETHODIMP get_localizedExtendedRole(BSTR* localizedExtendedRole) override;
STDMETHODIMP get_nExtendedStates(long* nExtendedStates) override;
STDMETHODIMP get_extendedStates(long maxExtendedStates, BSTR** extendedStates,
long* nExtendedStates) override;
STDMETHODIMP get_localizedExtendedStates(
long maxLocalizedExtendedStates, BSTR** localizedExtendedStates,
long* nLocalizedExtendedStates) override;
STDMETHODIMP get_uniqueID(long* uniqueID) override;
STDMETHODIMP get_windowHandle(HWND* windowHandle) override;
STDMETHODIMP get_indexInParent(long* indexInParent) override;
STDMETHODIMP get_locale(IA2Locale* locale) override;
STDMETHODIMP get_attributes(BSTR* attributes) override;
// IAccessible2_2
STDMETHODIMP get_attribute(BSTR name, VARIANT* attribute) override;
STDMETHODIMP get_accessibleWithCaret(IUnknown** accessible,
long* caretOffset) override;
STDMETHODIMP get_relationTargetsOfType(BSTR type, long maxTargets,
IUnknown*** targets,
long* nTargets) override;
// IAccessible2_3
STDMETHODIMP get_selectionRanges(IA2Range** ranges, long* nRanges) override;
// 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;
// IAccessibleTableCell
STDMETHODIMP get_columnExtent(long* nColumnsSpanned) override;
STDMETHODIMP get_columnHeaderCells(IUnknown*** cellAccessibles,
long* nColumnHeaderCells) override;
STDMETHODIMP get_columnIndex(long* columnIndex) override;
STDMETHODIMP get_rowExtent(long* nRowsSpanned) override;
STDMETHODIMP get_rowHeaderCells(IUnknown*** cellAccessibles,
long* nRowHeaderCells) override;
STDMETHODIMP get_rowIndex(long* rowIndex) override;
STDMETHODIMP get_isSelected(boolean* isSelected) override;
STDMETHODIMP get_rowColumnExtents(long* row, long* column, long* rowExtents,
long* columnExtents,
boolean* isSelected) override;
STDMETHODIMP get_table(IUnknown** table) override;
// IAccessibleText
STDMETHODIMP addSelection(long startOffset, long endOffset) override;
STDMETHODIMP get_attributes(long offset, long* startOffset, long* endOffset,
BSTR* textAttributes) override;
STDMETHODIMP get_caretOffset(long* offset) override;
STDMETHODIMP get_characterExtents(long offset,
enum IA2CoordinateType coordType, long* x,
long* y, long* width,
long* height) override;
STDMETHODIMP get_nSelections(long* nSelections) override;
STDMETHODIMP get_offsetAtPoint(long x, long y,
enum IA2CoordinateType coordType,
long* offset) override;
STDMETHODIMP get_selection(long selectionIndex, long* startOffset,
long* endOffset) override;
STDMETHODIMP get_text(long startOffset, long endOffset, BSTR* text) override;
STDMETHODIMP get_textBeforeOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long* startOffset, long* endOffset,
BSTR* text) override;
STDMETHODIMP get_textAfterOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long* startOffset, long* endOffset,
BSTR* text) override;
STDMETHODIMP get_textAtOffset(long offset,
enum IA2TextBoundaryType boundaryType,
long* startOffset, long* endOffset,
BSTR* text) override;
STDMETHODIMP removeSelection(long selectionIndex) override;
STDMETHODIMP setCaretOffset(long offset) override;
STDMETHODIMP setSelection(long selectionIndex, long startOffset,
long endOffset) override;
STDMETHODIMP get_nCharacters(long* nCharacters) override;
STDMETHODIMP scrollSubstringTo(long startIndex, long endIndex,
enum IA2ScrollType scrollType) override;
STDMETHODIMP scrollSubstringToPoint(long startIndex, long endIndex,
enum IA2CoordinateType coordinateType,
long x, long y) override;
STDMETHODIMP get_newText(IA2TextSegment* newText) override;
STDMETHODIMP get_oldText(IA2TextSegment* oldText) override;
// IAccessibleHypertext
STDMETHODIMP get_nHyperlinks(long* hyperlinkCount) override;
STDMETHODIMP get_hyperlink(long index,
IAccessibleHyperlink** hyperlink) override;
STDMETHODIMP get_hyperlinkIndex(long charIndex,
long* hyperlinkIndex) override;
// IAccessibleHypertext2
STDMETHODIMP get_hyperlinks(IAccessibleHyperlink*** hyperlinks,
long* nHyperlinks) override;
private:
AccessibleHandler(IUnknown* aOuter, HRESULT* aResult);
virtual ~AccessibleHandler();
HRESULT ResolveIA2();
HRESULT ResolveIDispatch();
HRESULT ResolveIAHyperlink();
HRESULT ResolveIAHypertext();
HRESULT ResolveIATableCell();
HRESULT MaybeUpdateCachedData();
HRESULT GetAllTextInfo(BSTR* aText);
void ClearTextCache();
HRESULT GetRelationsInfo();
void ClearRelationCache();
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
* references to the aggregated objects. OTOH, any interfaces that are QI'd
* from those aggregated objects have delegated unknowns.
*
* AddRef'ing an interface with a delegated unknown ends up incrementing the
* refcount of the *aggregator*. Since we are the aggregator of mDispatchUnk
* and of the wrapped proxy, holding a strong reference to any interfaces
* QI'd off of those objects would create a reference cycle.
*
* We may hold onto pointers to those references, but when we query them we
* 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
IAccessibleTableCell* mIATableCellPassThru; // weak
IAccessibleHypertext2* mIAHypertextPassThru; // weak
IA2Payload mCachedData;
bool mCachedDynamicDataMarshaledByCom;
UniquePtr<mscom::StructToStream> mSerializer;
uint32_t mCacheGen;
IAccessibleHyperlink** mCachedHyperlinks;
long mCachedNHyperlinks;
IA2TextSegment* mCachedTextAttribRuns;
long mCachedNTextAttribRuns;
IARelationData* mCachedRelations;
long mCachedNRelations;
bool mIsEmulatedWindow;
};
inline static BSTR CopyBSTR(BSTR aSrc) {
if (!aSrc) {
return nullptr;
}
return ::SysAllocStringLen(aSrc, ::SysStringLen(aSrc));
}
} // namespace a11y
} // namespace mozilla
# endif // !defined(MOZILLA_INTERNAL_API)
#endif // defined(__midl)
#endif // mozilla_a11y_AccessibleHandler_h

View File

@ -1,5 +0,0 @@
/* 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/. */
1 typelib HandlerData.tlb

View File

@ -1,221 +0,0 @@
/* -*- 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 "AccessibleHandlerControl.h"
#include <utility>
#include "AccessibleEventId.h"
#include "AccessibleHandler.h"
#include "mozilla/RefPtr.h"
namespace mozilla {
namespace a11y {
mscom::SingletonFactory<AccessibleHandlerControl> gControlFactory;
namespace detail {
TextChange::TextChange() : mIA2UniqueId(0), mIsInsert(false), mText() {}
TextChange::TextChange(long aIA2UniqueId, bool aIsInsert,
NotNull<IA2TextSegment*> aText)
: mIA2UniqueId(aIA2UniqueId),
mIsInsert(aIsInsert),
mText{BSTRCopy(aText->text), aText->start, aText->end} {}
TextChange::TextChange(TextChange&& aOther) : mText() {
*this = std::move(aOther);
}
TextChange::TextChange(const TextChange& aOther) : mText() { *this = aOther; }
TextChange& TextChange::operator=(TextChange&& aOther) {
mIA2UniqueId = aOther.mIA2UniqueId;
mIsInsert = aOther.mIsInsert;
aOther.mIA2UniqueId = 0;
::SysFreeString(mText.text);
mText = aOther.mText;
aOther.mText.text = nullptr;
return *this;
}
TextChange& TextChange::operator=(const TextChange& aOther) {
mIA2UniqueId = aOther.mIA2UniqueId;
mIsInsert = aOther.mIsInsert;
::SysFreeString(mText.text);
mText = {BSTRCopy(aOther.mText.text), aOther.mText.start, aOther.mText.end};
return *this;
}
TextChange::~TextChange() { ::SysFreeString(mText.text); }
HRESULT
TextChange::GetOld(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutOldSegment) {
if (mIsInsert || aIA2UniqueId != mIA2UniqueId) {
return S_OK;
}
return SegCopy(*aOutOldSegment, mText);
}
HRESULT
TextChange::GetNew(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutNewSegment) {
if (!mIsInsert || aIA2UniqueId != mIA2UniqueId) {
return S_OK;
}
return SegCopy(*aOutNewSegment, mText);
}
/* static */
BSTR TextChange::BSTRCopy(const BSTR& aIn) {
return ::SysAllocStringLen(aIn, ::SysStringLen(aIn));
}
/* static */
HRESULT TextChange::SegCopy(IA2TextSegment& aDest, const IA2TextSegment& aSrc) {
aDest = {BSTRCopy(aSrc.text), aSrc.start, aSrc.end};
if (aSrc.text && !aDest.text) {
return E_OUTOFMEMORY;
}
if (!::SysStringLen(aDest.text)) {
return S_FALSE;
}
return S_OK;
}
} // namespace detail
HRESULT
AccessibleHandlerControl::Create(AccessibleHandlerControl** aOutObject) {
if (!aOutObject) {
return E_INVALIDARG;
}
RefPtr<AccessibleHandlerControl> ctl(new AccessibleHandlerControl());
ctl.forget(aOutObject);
return S_OK;
}
AccessibleHandlerControl::AccessibleHandlerControl()
: mIsRegistered(false),
mCacheGen(0),
mIA2Proxy(mscom::RegisterProxy(L"ia2marshal.dll")),
mHandlerProxy(mscom::RegisterProxy()) {
MOZ_ASSERT(mIA2Proxy);
}
IMPL_IUNKNOWN1(AccessibleHandlerControl, IHandlerControl)
HRESULT
AccessibleHandlerControl::Invalidate() {
++mCacheGen;
// We can't just call mAccessibleCache.clear() because doing so would release
// remote objects, making remote COM calls. Since this is an STA, an incoming
// COM call might be handled which might marshal an AccessibleHandler,
// which in turn might add itself to mAccessibleCache. Since we'd be in the
// middle of mutating mAccessibleCache, that might cause a crash. Instead,
// swap mAccessibleCache into a temporary map first, which will empty
// mAccessibleCache without releasing remote objects. Once mAccessibleCache
// is empty, it's safe to let the temporary map be destroyed when it goes
// out of scope. Remote calls will be made, but nothing will re-enter
// the temporary map while it's being destroyed.
AccessibleCache oldCache;
mAccessibleCache.swap(oldCache);
return S_OK;
}
HRESULT
AccessibleHandlerControl::OnTextChange(long aHwnd, long aIA2UniqueId,
VARIANT_BOOL aIsInsert,
IA2TextSegment* aText) {
if (!aText) {
return E_INVALIDARG;
}
mTextChange = detail::TextChange(aIA2UniqueId, aIsInsert, WrapNotNull(aText));
NotifyWinEvent(aIsInsert ? IA2_EVENT_TEXT_INSERTED : IA2_EVENT_TEXT_REMOVED,
reinterpret_cast<HWND>(static_cast<uintptr_t>(aHwnd)),
OBJID_CLIENT, aIA2UniqueId);
return S_OK;
}
HRESULT
AccessibleHandlerControl::GetNewText(long aIA2UniqueId,
NotNull<IA2TextSegment*> aOutNewText) {
return mTextChange.GetNew(aIA2UniqueId, aOutNewText);
}
HRESULT
AccessibleHandlerControl::GetOldText(long aIA2UniqueId,
NotNull<IA2TextSegment*> aOutOldText) {
return mTextChange.GetOld(aIA2UniqueId, aOutOldText);
}
HRESULT
AccessibleHandlerControl::GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo) {
if (!mHandlerProxy) {
return E_UNEXPECTED;
}
return mHandlerProxy->GetTypeInfoForGuid(CLSID_AccessibleHandler,
aOutTypeInfo);
}
HRESULT
AccessibleHandlerControl::Register(NotNull<IGeckoBackChannel*> aGecko) {
if (mIsRegistered) {
return S_OK;
}
long pid = static_cast<long>(::GetCurrentProcessId());
HRESULT hr = aGecko->put_HandlerControl(pid, this);
mIsRegistered = SUCCEEDED(hr);
MOZ_ASSERT(mIsRegistered);
return hr;
}
void AccessibleHandlerControl::CacheAccessible(long aUniqueId,
AccessibleHandler* aAccessible) {
MOZ_ASSERT(aUniqueId && aAccessible);
mAccessibleCache[aUniqueId] = aAccessible;
}
HRESULT AccessibleHandlerControl::GetCachedAccessible(
long aUniqueId, AccessibleHandler** aAccessible) {
MOZ_ASSERT(aUniqueId && aAccessible);
auto it = mAccessibleCache.find(aUniqueId);
if (it == mAccessibleCache.end()) {
return E_INVALIDARG;
}
RefPtr<AccessibleHandler> ref = it->second;
ref.forget(aAccessible);
return S_OK;
}
HRESULT AccessibleHandlerControl::SuppressA11yForClipboardCopy() {
mA11yClipboardCopySuppressionStartTime = ::GetTickCount();
return S_OK;
}
bool AccessibleHandlerControl::IsA11ySuppressedForClipboardCopy() {
// Must be kept in sync with kSuppressTimeout in
// accessible/windows/msaa/Compatibility.cpp.
constexpr DWORD kSuppressTimeout = 1500; // ms
if (!mA11yClipboardCopySuppressionStartTime) {
return false;
}
return ::GetTickCount() - mA11yClipboardCopySuppressionStartTime <
kSuppressTimeout;
}
} // namespace a11y
} // namespace mozilla

View File

@ -1,103 +0,0 @@
/* -*- 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)
#ifndef mozilla_a11y_AccessibleHandlerControl_h
# define mozilla_a11y_AccessibleHandlerControl_h
# include <unordered_map>
# include "Factory.h"
# include "HandlerData.h"
# include "IUnknownImpl.h"
# include "mozilla/mscom/Registration.h"
# include "mozilla/NotNull.h"
namespace mozilla {
namespace a11y {
namespace detail {
class TextChange final {
public:
TextChange();
TextChange(long aIA2UniqueId, bool aIsInsert, NotNull<IA2TextSegment*> aText);
TextChange(TextChange&& aOther);
TextChange(const TextChange& aOther);
TextChange& operator=(TextChange&& aOther);
TextChange& operator=(const TextChange& aOther);
~TextChange();
HRESULT GetOld(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutOldSegment);
HRESULT GetNew(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutNewSegment);
private:
static BSTR BSTRCopy(const BSTR& aIn);
static HRESULT SegCopy(IA2TextSegment& aDest, const IA2TextSegment& aSrc);
long mIA2UniqueId;
bool mIsInsert;
IA2TextSegment mText;
};
} // namespace detail
class AccessibleHandler;
class AccessibleHandlerControl final : public IHandlerControl {
public:
static HRESULT Create(AccessibleHandlerControl** aOutObject);
DECL_IUNKNOWN
// IHandlerControl
STDMETHODIMP Invalidate() override;
STDMETHODIMP OnTextChange(long aHwnd, long aIA2UniqueId,
VARIANT_BOOL aIsInsert,
IA2TextSegment* aText) override;
STDMETHODIMP SuppressA11yForClipboardCopy() override;
uint32_t GetCacheGen() const { return mCacheGen; }
HRESULT GetNewText(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutNewText);
HRESULT GetOldText(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutOldText);
HRESULT GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo);
HRESULT Register(NotNull<IGeckoBackChannel*> aGecko);
void CacheAccessible(long aUniqueId, AccessibleHandler* aAccessible);
HRESULT GetCachedAccessible(long aUniqueId, AccessibleHandler** aAccessible);
bool IsA11ySuppressedForClipboardCopy();
private:
AccessibleHandlerControl();
~AccessibleHandlerControl() = default;
bool mIsRegistered;
uint32_t mCacheGen;
detail::TextChange mTextChange;
UniquePtr<mscom::RegisteredProxy> mIA2Proxy;
UniquePtr<mscom::RegisteredProxy> mHandlerProxy;
// We can't use Gecko APIs in this dll, hence the use of std::unordered_map.
typedef std::unordered_map<long, RefPtr<AccessibleHandler>> AccessibleCache;
AccessibleCache mAccessibleCache;
// Time when SuppressA11yForClipboardCopy() was called, as returned by
// ::GetTickCount().
DWORD mA11yClipboardCopySuppressionStartTime = 0;
};
extern mscom::SingletonFactory<AccessibleHandlerControl> gControlFactory;
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_AccessibleHandlerControl_h

View File

@ -1,170 +0,0 @@
/* -*- 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 "HandlerChildEnumerator.h"
#include "HandlerTextLeaf.h"
#include "mozilla/Assertions.h"
namespace mozilla {
namespace a11y {
HandlerChildEnumerator::HandlerChildEnumerator(
AccessibleHandler* aHandler, IGeckoBackChannel* aGeckoBackChannel)
: mHandler(aHandler),
mGeckoBackChannel(aGeckoBackChannel),
mChildCount(0),
mNextChild(0) {
MOZ_ASSERT(aHandler);
MOZ_ASSERT(aGeckoBackChannel);
}
HandlerChildEnumerator::HandlerChildEnumerator(
const HandlerChildEnumerator& aEnumerator)
: mHandler(aEnumerator.mHandler),
mGeckoBackChannel(aEnumerator.mGeckoBackChannel),
mChildCount(aEnumerator.mChildCount),
mNextChild(aEnumerator.mNextChild) {
if (mChildCount == 0) {
return;
}
mChildren = MakeUnique<VARIANT[]>(mChildCount);
CopyMemory(mChildren.get(), aEnumerator.mChildren.get(),
sizeof(VARIANT) * mChildCount);
for (ULONG index = 0; index < mChildCount; ++index) {
mChildren[index].pdispVal->AddRef();
}
}
HandlerChildEnumerator::~HandlerChildEnumerator() { ClearCache(); }
void HandlerChildEnumerator::ClearCache() {
if (!mChildren) {
return;
}
for (ULONG index = 0; index < mChildCount; ++index) {
mChildren[index].pdispVal->Release();
}
mChildren = nullptr;
mChildCount = 0;
}
HRESULT
HandlerChildEnumerator::MaybeCacheChildren() {
if (mChildren) {
// Already cached.
return S_OK;
}
AccChildData* children;
HRESULT hr = mGeckoBackChannel->get_AllChildren(&children, &mChildCount);
if (FAILED(hr)) {
mChildCount = 0;
ClearCache();
return hr;
}
HWND hwnd = nullptr;
hr = mHandler->get_windowHandle(&hwnd);
MOZ_ASSERT(SUCCEEDED(hr));
RefPtr<IDispatch> parent;
hr = mHandler->QueryInterface(IID_IDispatch, getter_AddRefs(parent));
MOZ_ASSERT(SUCCEEDED(hr));
mChildren = MakeUnique<VARIANT[]>(mChildCount);
for (ULONG index = 0; index < mChildCount; ++index) {
AccChildData& data = children[index];
VARIANT& child = mChildren[index];
if (data.mAccessible) {
RefPtr<IDispatch> disp;
hr =
data.mAccessible->QueryInterface(IID_IDispatch, getter_AddRefs(disp));
data.mAccessible->Release();
MOZ_ASSERT(SUCCEEDED(hr));
if (FAILED(hr)) {
child.vt = VT_EMPTY;
continue;
}
child.vt = VT_DISPATCH;
disp.forget(&child.pdispVal);
} else {
// Text leaf.
RefPtr<IDispatch> leaf(new HandlerTextLeaf(parent, index, hwnd, data));
child.vt = VT_DISPATCH;
leaf.forget(&child.pdispVal);
}
}
::CoTaskMemFree(children);
return S_OK;
}
IMPL_IUNKNOWN_QUERY_HEAD(HandlerChildEnumerator)
IMPL_IUNKNOWN_QUERY_IFACE(IEnumVARIANT)
IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mHandler)
/*** IEnumVARIANT ***/
HRESULT
HandlerChildEnumerator::Clone(IEnumVARIANT** aPpEnum) {
RefPtr<HandlerChildEnumerator> newEnum(new HandlerChildEnumerator(*this));
newEnum.forget(aPpEnum);
return S_OK;
}
HRESULT
HandlerChildEnumerator::Next(ULONG aCelt, VARIANT* aRgVar,
ULONG* aPCeltFetched) {
if (!aRgVar || aCelt == 0) {
return E_INVALIDARG;
}
HRESULT hr = MaybeCacheChildren();
if (FAILED(hr)) {
return hr;
}
for (ULONG index = 0; index < aCelt; ++index) {
if (mNextChild >= mChildCount) {
// Less elements remaining than were requested.
if (aPCeltFetched) {
*aPCeltFetched = index;
}
return S_FALSE;
}
aRgVar[index] = mChildren[mNextChild];
aRgVar[index].pdispVal->AddRef();
++mNextChild;
}
*aPCeltFetched = aCelt;
return S_OK;
}
HRESULT
HandlerChildEnumerator::Reset() {
mNextChild = 0;
ClearCache();
return S_OK;
}
HRESULT
HandlerChildEnumerator::Skip(ULONG aCelt) {
mNextChild += aCelt;
if (mNextChild > mChildCount) {
// Less elements remaining than the client requested to skip.
return S_FALSE;
}
return S_OK;
}
} // namespace a11y
} // namespace mozilla

View File

@ -1,51 +0,0 @@
/* -*- 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)
#ifndef mozilla_a11y_HandlerChildEnumerator_h
# define mozilla_a11y_HandlerChildEnumerator_h
# include "AccessibleHandler.h"
# include "IUnknownImpl.h"
# include "mozilla/RefPtr.h"
namespace mozilla {
namespace a11y {
class HandlerChildEnumerator final : public IEnumVARIANT {
public:
explicit HandlerChildEnumerator(AccessibleHandler* aHandler,
IGeckoBackChannel* aGeckoBackChannel);
DECL_IUNKNOWN
// IEnumVARIANT
STDMETHODIMP Clone(IEnumVARIANT** aPpEnum) override;
STDMETHODIMP Next(ULONG aCelt, VARIANT* aRgVar,
ULONG* aPCeltFetched) override;
STDMETHODIMP Reset() override;
STDMETHODIMP Skip(ULONG aCelt) override;
private:
explicit HandlerChildEnumerator(const HandlerChildEnumerator& aEnumerator);
~HandlerChildEnumerator();
void ClearCache();
HRESULT MaybeCacheChildren();
RefPtr<AccessibleHandler> mHandler;
RefPtr<IGeckoBackChannel> mGeckoBackChannel;
UniquePtr<VARIANT[]> mChildren;
ULONG mChildCount;
ULONG mNextChild;
};
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_HandlerChildEnumerator_h

View File

@ -1,11 +0,0 @@
/* -*- 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/. */
[explicit_handle]
interface HandlerData
{
typedef [encode,decode] IA2Payload;
}

View File

@ -1,155 +0,0 @@
/* -*- 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/. */
#include "mozilla-config.h"
#include "AccessibleHandler.h"
#include "HandlerDataUUID.h"
import "ocidl.idl";
import "servprov.idl";
import "Accessible2_3.idl";
import "AccessibleHypertext2.idl";
import "AccessibleHyperlink.idl";
import "AccessibleTable.idl";
import "AccessibleTable2.idl";
import "AccessibleTableCell.idl";
typedef struct _StaticIA2Data
{
NEWEST_IA2_INTERFACE* mIA2;
IAccessibleHypertext2* mIAHypertext;
IAccessibleHyperlink* mIAHyperlink;
IAccessibleTable* mIATable;
IAccessibleTable2* mIATable2;
IAccessibleTableCell* mIATableCell;
} StaticIA2Data;
typedef struct _DynamicIA2Data
{
// From IAccessible/IAccessible2
VARIANT mRole;
long mState;
long mChildCount;
long mIA2Role;
AccessibleStates mIA2States;
long mLeft;
long mTop;
long mWidth;
long mHeight;
long mHwnd;
BSTR mKeyboardShortcut;
BSTR mName;
BSTR mDescription;
BSTR mDefaultAction;
BSTR mValue;
BSTR mAttributes;
IA2Locale mIA2Locale;
// From IAccessibleAction
long mNActions;
// From IAccessibleTableCell
long mRowIndex;
long mColumnIndex;
long mRowExtent;
long mColumnExtent;
boolean mCellIsSelected;
long mNRowHeaderCells;
[size_is(mNRowHeaderCells)] long* mRowHeaderCellIds;
long mNColumnHeaderCells;
[size_is(mNColumnHeaderCells)] long* mColumnHeaderCellIds;
// From IAccessible2
long mUniqueId;
} DynamicIA2Data;
interface IGeckoBackChannel;
[uuid(2b0e83b3-fd1a-443f-9ed6-c00d39055b58)]
interface HandlerData
{
typedef struct _IA2Payload
{
StaticIA2Data mStaticData;
DynamicIA2Data mDynamicData;
IGeckoBackChannel* mGeckoBackChannel;
} IA2Payload;
}
[object,
uuid(IHANDLERCONTROL_IID),
async_uuid(ASYNCIHANDLERCONTROL_IID),
pointer_default(unique)]
interface IHandlerControl : IUnknown
{
HRESULT Invalidate();
HRESULT OnTextChange([in] long aHwnd, [in] long aIA2UniqueId,
[in] VARIANT_BOOL aIsInsert,
[in] IA2TextSegment* aText);
HRESULT SuppressA11yForClipboardCopy();
}
typedef struct _IARelationData
{
BSTR mType;
long mNTargets;
} IARelationData;
typedef struct _AccChildData
{
NEWEST_IA2_INTERFACE* mAccessible;
BSTR mText;
long mTextRole;
long mTextId;
long mTextState;
long mTextLeft;
long mTextTop;
long mTextWidth;
long mTextHeight;
} AccChildData;
[object,
uuid(IGECKOBACKCHANNEL_IID),
pointer_default(unique)]
interface IGeckoBackChannel : IUnknown
{
[propput] HRESULT HandlerControl([in] long aPid, [in] IHandlerControl* aCtrl);
HRESULT Refresh([out] DynamicIA2Data* aOutData);
[propget] HRESULT AllTextInfo([out] BSTR* aText,
[out, size_is(,*aNHyperlinks)] IAccessibleHyperlink*** aHyperlinks,
[out] long* aNHyperlinks,
[out, size_is(,*aNAttribRuns)] IA2TextSegment** aAttribRuns,
[out] long* aNAttribRuns);
[propget] HRESULT RelationsInfo(
[out, size_is(,*aNRelations)] IARelationData** aRelations,
[out] long* aNRelations);
[propget] HRESULT AllChildren(
[out, size_is(,*aNChildren)] AccChildData** aChildren,
[out] ULONG* aNChildren);
}
[uuid(1e545f07-f108-4912-9471-546827a80983)]
library AccessibleHandlerTypeLib
{
importlib("stdole2.tlb");
/**
* This definition is required in order for the handler implementation to
* support IDispatch (aka Automation). This is used by interpreted language
* FFIs to discover which interfaces may be controlled via IDispatch.
* (In particular, the python FFI used by NVDA needs this).
*
* In reality, the only a11y interface that is Automation compliant is
* IAccessible; our remaining interfaces are not.
*
* Once the FFI knows that IAccessible is supported, the FFI queries for
* IAccessible and is then able to resolve non-automation interfaces from
* there.
*/
[uuid(HANDLER_CLSID)]
coclass AccessibleHandler
{
[default] interface IAccessible;
};
};

View File

@ -1,95 +0,0 @@
/* -*- 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/. */
#ifndef mozilla_a11y_HandlerDataCleanup_h
#define mozilla_a11y_HandlerDataCleanup_h
#include <oleauto.h>
namespace mozilla {
namespace a11y {
inline void ReleaseStaticIA2DataInterfaces(StaticIA2Data& aData) {
// Only interfaces of the proxied object wrapped by this handler should be
// released here, never other objects!
// For example, if StaticIA2Data were to include accParent in future,
// that must not be released here.
if (aData.mIA2) {
aData.mIA2->Release();
}
if (aData.mIAHypertext) {
aData.mIAHypertext->Release();
}
if (aData.mIAHyperlink) {
aData.mIAHyperlink->Release();
}
if (aData.mIATable) {
aData.mIATable->Release();
}
if (aData.mIATable2) {
aData.mIATable2->Release();
}
if (aData.mIATableCell) {
aData.mIATableCell->Release();
}
}
/**
* Pass true for aMarshaledByCom if this struct was directly marshaled as an
* out parameter of a COM method, currently only IGeckoBackChannel::Refresh.
*/
inline void CleanupDynamicIA2Data(DynamicIA2Data& aData,
bool aMarshaledByCom = false) {
// If freeing generic memory returned to the client, you *must* use freeMem,
// not CoTaskMemFree!
auto freeMem = [aMarshaledByCom](void* aMem) {
if (aMarshaledByCom) {
::CoTaskMemFree(aMem);
} else {
::midl_user_free(aMem);
}
};
::VariantClear(&aData.mRole);
if (aData.mKeyboardShortcut) {
::SysFreeString(aData.mKeyboardShortcut);
}
if (aData.mName) {
::SysFreeString(aData.mName);
}
if (aData.mDescription) {
::SysFreeString(aData.mDescription);
}
if (aData.mDefaultAction) {
::SysFreeString(aData.mDefaultAction);
}
if (aData.mValue) {
::SysFreeString(aData.mValue);
}
if (aData.mAttributes) {
::SysFreeString(aData.mAttributes);
}
if (aData.mIA2Locale.language) {
::SysFreeString(aData.mIA2Locale.language);
}
if (aData.mIA2Locale.country) {
::SysFreeString(aData.mIA2Locale.country);
}
if (aData.mIA2Locale.variant) {
::SysFreeString(aData.mIA2Locale.variant);
}
if (aData.mRowHeaderCellIds) {
freeMem(aData.mRowHeaderCellIds);
}
if (aData.mColumnHeaderCellIds) {
freeMem(aData.mColumnHeaderCellIds);
}
}
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_HandlerDataCleanup_h

View File

@ -1,16 +0,0 @@
/* -*- 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/. */
// We use different CLSIDs and IIDs depending on channel and officiality.
// This prevents handlers from installing overtop one another when multiple
// channels are present. Note that we only do this for the UUIDs that are
// written to the registry.
// The specific UUIDs are defined in branding configuration.
#define HANDLER_CLSID @MOZ_HANDLER_CLSID@
#define IHANDLERCONTROL_IID @MOZ_IHANDLERCONTROL_IID@
#define ASYNCIHANDLERCONTROL_IID @MOZ_ASYNCIHANDLERCONTROL_IID@
#define IGECKOBACKCHANNEL_IID @MOZ_IGECKOBACKCHANNEL_IID@

View File

@ -1,138 +0,0 @@
/* -*- 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

View File

@ -1,46 +0,0 @@
/* -*- 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)
#ifndef mozilla_a11y_HandlerRelation_h
# define mozilla_a11y_HandlerRelation_h
# include "AccessibleHandler.h"
# include "IUnknownImpl.h"
# include "mozilla/RefPtr.h"
namespace mozilla {
namespace a11y {
class HandlerRelation final : public IAccessibleRelation {
public:
explicit HandlerRelation(AccessibleHandler* aHandler, IARelationData& aData);
DECL_IUNKNOWN
// IAccessibleRelation
STDMETHODIMP get_relationType(BSTR* aType) override;
STDMETHODIMP get_localizedRelationType(BSTR* aLocalizedType) override;
STDMETHODIMP get_nTargets(long* aNTargets) override;
STDMETHODIMP get_target(long aIndex, IUnknown** aTarget) override;
STDMETHODIMP get_targets(long aMaxTargets, IUnknown** aTargets,
long* aNTargets) override;
private:
virtual ~HandlerRelation();
HRESULT GetTargets();
RefPtr<AccessibleHandler> mHandler;
IARelationData mData;
IUnknown** mTargets;
};
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_HandlerRelation_h

View File

@ -1,337 +0,0 @@
/* -*- 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 "HandlerTextLeaf.h"
#include "mozilla/Assertions.h"
namespace mozilla {
namespace a11y {
HandlerTextLeaf::HandlerTextLeaf(IDispatch* aParent, long aIndexInParent,
HWND aHwnd, AccChildData& aData)
: mParent(aParent),
mIndexInParent(aIndexInParent),
mHwnd(aHwnd),
mData(aData) {
MOZ_ASSERT(aParent);
}
HandlerTextLeaf::~HandlerTextLeaf() {
if (mData.mText) {
::SysFreeString(mData.mText);
}
}
IMPL_IUNKNOWN_QUERY_HEAD(HandlerTextLeaf)
IMPL_IUNKNOWN_QUERY_IFACE(IDispatch)
IMPL_IUNKNOWN_QUERY_IFACE(IAccessible)
IMPL_IUNKNOWN_QUERY_IFACE(IAccessible2)
IMPL_IUNKNOWN_QUERY_IFACE(IServiceProvider)
IMPL_IUNKNOWN_QUERY_TAIL
/*** IDispatch ***/
HRESULT
HandlerTextLeaf::GetTypeInfoCount(UINT* pctinfo) { return E_NOTIMPL; }
HRESULT
HandlerTextLeaf::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgDispId) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS* pDispParams,
VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
UINT* puArgErr) {
return E_NOTIMPL;
}
/*** IAccessible ***/
HRESULT
HandlerTextLeaf::get_accParent(IDispatch** ppdispParent) {
if (!ppdispParent) {
return E_INVALIDARG;
}
RefPtr<IDispatch> parent(mParent);
parent.forget(ppdispParent);
return S_OK;
}
HRESULT
HandlerTextLeaf::get_accChildCount(long* pcountChildren) {
if (!pcountChildren) {
return E_INVALIDARG;
}
*pcountChildren = 0;
return S_OK;
}
HRESULT
HandlerTextLeaf::get_accChild(VARIANT varChild, IDispatch** ppdispChild) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::get_accName(VARIANT varChild, BSTR* pszName) {
if (varChild.lVal != CHILDID_SELF || !pszName) {
return E_INVALIDARG;
}
*pszName = CopyBSTR(mData.mText);
return S_OK;
}
HRESULT
HandlerTextLeaf::get_accValue(VARIANT varChild, BSTR* pszValue) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::get_accDescription(VARIANT varChild, BSTR* pszDescription) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::get_accRole(VARIANT varChild, VARIANT* pvarRole) {
if (varChild.lVal != CHILDID_SELF || !pvarRole) {
return E_INVALIDARG;
}
pvarRole->vt = VT_I4;
pvarRole->lVal = mData.mTextRole;
return S_OK;
}
HRESULT
HandlerTextLeaf::get_accState(VARIANT varChild, VARIANT* pvarState) {
if (varChild.lVal != CHILDID_SELF || !pvarState) {
return E_INVALIDARG;
}
pvarState->vt = VT_I4;
pvarState->lVal = mData.mTextState;
return S_OK;
}
HRESULT
HandlerTextLeaf::get_accHelp(VARIANT varChild, BSTR* pszHelp) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::get_accHelpTopic(BSTR* pszHelpFile, VARIANT varChild,
long* pidTopic) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::get_accKeyboardShortcut(VARIANT varChild,
BSTR* pszKeyboardShortcut) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::get_accFocus(VARIANT* pvarChild) { return E_NOTIMPL; }
HRESULT
HandlerTextLeaf::get_accSelection(VARIANT* pvarChildren) { return E_NOTIMPL; }
HRESULT
HandlerTextLeaf::get_accDefaultAction(VARIANT varChild,
BSTR* pszDefaultAction) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::accSelect(long flagsSelect, VARIANT varChild) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::accLocation(long* pxLeft, long* pyTop, long* pcxWidth,
long* pcyHeight, VARIANT varChild) {
if (varChild.lVal != CHILDID_SELF || !pxLeft || !pyTop || !pcxWidth ||
!pcyHeight) {
return E_INVALIDARG;
}
*pxLeft = mData.mTextLeft;
*pyTop = mData.mTextTop;
*pcxWidth = mData.mTextWidth;
*pcyHeight = mData.mTextHeight;
return S_OK;
}
HRESULT
HandlerTextLeaf::accNavigate(long navDir, VARIANT varStart,
VARIANT* pvarEndUpAt) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::accHitTest(long xLeft, long yTop, VARIANT* pvarChild) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::accDoDefaultAction(VARIANT varChild) { return E_NOTIMPL; }
HRESULT
HandlerTextLeaf::put_accName(VARIANT varChild, BSTR szName) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::put_accValue(VARIANT varChild, BSTR szValue) {
return E_NOTIMPL;
}
/*** IAccessible2 ***/
HRESULT
HandlerTextLeaf::get_nRelations(long* nRelations) { return E_NOTIMPL; }
HRESULT
HandlerTextLeaf::get_relation(long relationIndex,
IAccessibleRelation** relation) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::get_relations(long maxRelations,
IAccessibleRelation** relations,
long* nRelations) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::role(long* role) {
if (!role) {
return E_INVALIDARG;
}
*role = mData.mTextRole;
return S_OK;
}
HRESULT
HandlerTextLeaf::scrollTo(IA2ScrollType scrollType) { return E_NOTIMPL; }
HRESULT
HandlerTextLeaf::scrollToPoint(IA2CoordinateType coordinateType, long x,
long y) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::get_groupPosition(long* groupLevel, long* similarItemsInGroup,
long* positionInGroup) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::get_states(AccessibleStates* states) {
if (!states) {
return E_INVALIDARG;
}
*states = 0;
return S_OK;
}
HRESULT
HandlerTextLeaf::get_extendedRole(BSTR* extendedRole) { return E_NOTIMPL; }
HRESULT
HandlerTextLeaf::get_localizedExtendedRole(BSTR* localizedExtendedRole) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::get_nExtendedStates(long* nExtendedStates) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::get_extendedStates(long maxExtendedStates,
BSTR** extendedStates,
long* nExtendedStates) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::get_localizedExtendedStates(long maxLocalizedExtendedStates,
BSTR** localizedExtendedStates,
long* nLocalizedExtendedStates) {
return E_NOTIMPL;
}
HRESULT
HandlerTextLeaf::get_uniqueID(long* uniqueID) {
if (!uniqueID) {
return E_INVALIDARG;
}
*uniqueID = mData.mTextId;
return S_OK;
}
HRESULT
HandlerTextLeaf::get_windowHandle(HWND* windowHandle) {
if (!windowHandle) {
return E_INVALIDARG;
}
*windowHandle = mHwnd;
return S_OK;
}
HRESULT
HandlerTextLeaf::get_indexInParent(long* indexInParent) {
if (!indexInParent) {
return E_INVALIDARG;
}
*indexInParent = mIndexInParent;
return S_OK;
}
HRESULT
HandlerTextLeaf::get_locale(IA2Locale* locale) { return E_NOTIMPL; }
HRESULT
HandlerTextLeaf::get_attributes(BSTR* attributes) { return E_NOTIMPL; }
/*** IServiceProvider ***/
HRESULT
HandlerTextLeaf::QueryService(REFGUID aServiceId, REFIID aIid,
void** aOutInterface) {
if (aIid == IID_IAccessible2) {
RefPtr<IAccessible2> ia2(this);
ia2.forget(aOutInterface);
return S_OK;
}
return E_INVALIDARG;
}
} // namespace a11y
} // namespace mozilla

View File

@ -1,110 +0,0 @@
/* -*- 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)
#ifndef mozilla_a11y_HandlerTextLeaf_h
# define mozilla_a11y_HandlerTextLeaf_h
# include "AccessibleHandler.h"
# include "IUnknownImpl.h"
# include "mozilla/RefPtr.h"
namespace mozilla {
namespace a11y {
class HandlerTextLeaf final : public IAccessible2, public IServiceProvider {
public:
explicit HandlerTextLeaf(IDispatch* aParent, long aIndexInParent, HWND aHwnd,
AccChildData& aData);
DECL_IUNKNOWN
// IDispatch
STDMETHODIMP GetTypeInfoCount(UINT* pctinfo) override;
STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid,
ITypeInfo** ppTInfo) override;
STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgDispId) override;
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS* pDispParams, VARIANT* pVarResult,
EXCEPINFO* pExcepInfo, UINT* puArgErr) override;
// IAccessible
STDMETHODIMP get_accParent(IDispatch** ppdispParent) override;
STDMETHODIMP get_accChildCount(long* pcountChildren) override;
STDMETHODIMP get_accChild(VARIANT varChild, IDispatch** ppdispChild) override;
STDMETHODIMP get_accName(VARIANT varChild, BSTR* pszName) override;
STDMETHODIMP get_accValue(VARIANT varChild, BSTR* pszValue) override;
STDMETHODIMP get_accDescription(VARIANT varChild,
BSTR* pszDescription) override;
STDMETHODIMP get_accRole(VARIANT varChild, VARIANT* pvarRole) override;
STDMETHODIMP get_accState(VARIANT varChild, VARIANT* pvarState) override;
STDMETHODIMP get_accHelp(VARIANT varChild, BSTR* pszHelp) override;
STDMETHODIMP get_accHelpTopic(BSTR* pszHelpFile, VARIANT varChild,
long* pidTopic) override;
STDMETHODIMP get_accKeyboardShortcut(VARIANT varChild,
BSTR* pszKeyboardShortcut) override;
STDMETHODIMP get_accFocus(VARIANT* pvarChild) override;
STDMETHODIMP get_accSelection(VARIANT* pvarChildren) override;
STDMETHODIMP get_accDefaultAction(VARIANT varChild,
BSTR* pszDefaultAction) override;
STDMETHODIMP accSelect(long flagsSelect, VARIANT varChild) override;
STDMETHODIMP accLocation(long* pxLeft, long* pyTop, long* pcxWidth,
long* pcyHeight, VARIANT varChild) override;
STDMETHODIMP accNavigate(long navDir, VARIANT varStart,
VARIANT* pvarEndUpAt) override;
STDMETHODIMP accHitTest(long xLeft, long yTop, VARIANT* pvarChild) override;
STDMETHODIMP accDoDefaultAction(VARIANT varChild) override;
STDMETHODIMP put_accName(VARIANT varChild, BSTR szName) override;
STDMETHODIMP put_accValue(VARIANT varChild, BSTR szValue) override;
// IAccessible2
STDMETHODIMP get_nRelations(long* nRelations) override;
STDMETHODIMP get_relation(long relationIndex,
IAccessibleRelation** relation) override;
STDMETHODIMP get_relations(long maxRelations, IAccessibleRelation** relations,
long* nRelations) override;
STDMETHODIMP role(long* role) override;
STDMETHODIMP scrollTo(IA2ScrollType scrollType) override;
STDMETHODIMP scrollToPoint(IA2CoordinateType coordinateType, long x,
long y) override;
STDMETHODIMP get_groupPosition(long* groupLevel, long* similarItemsInGroup,
long* positionInGroup) override;
STDMETHODIMP get_states(AccessibleStates* states) override;
STDMETHODIMP get_extendedRole(BSTR* extendedRole) override;
STDMETHODIMP get_localizedExtendedRole(BSTR* localizedExtendedRole) override;
STDMETHODIMP get_nExtendedStates(long* nExtendedStates) override;
STDMETHODIMP get_extendedStates(long maxExtendedStates, BSTR** extendedStates,
long* nExtendedStates) override;
STDMETHODIMP get_localizedExtendedStates(
long maxLocalizedExtendedStates, BSTR** localizedExtendedStates,
long* nLocalizedExtendedStates) override;
STDMETHODIMP get_uniqueID(long* uniqueID) override;
STDMETHODIMP get_windowHandle(HWND* windowHandle) override;
STDMETHODIMP get_indexInParent(long* indexInParent) override;
STDMETHODIMP get_locale(IA2Locale* locale) override;
STDMETHODIMP get_attributes(BSTR* attributes) override;
// IServiceProvider
STDMETHODIMP QueryService(REFGUID aServiceId, REFIID aIid,
void** aOutInterface) override;
private:
~HandlerTextLeaf();
RefPtr<IDispatch> mParent;
long mIndexInParent;
HWND mHwnd;
AccChildData mData;
};
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_HandlerTextLeaf_h

View File

@ -1,132 +0,0 @@
# -*- 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/.
SharedLibrary("AccessibleHandler")
EXPORTS.mozilla.a11y += [
"AccessibleHandler.h",
"HandlerDataCleanup.h",
]
LOCAL_INCLUDES += [
"/accessible/interfaces/ia2",
"/ipc/mscom/oop",
]
# We want to generate distinct UUIDs on a per-channel basis, so we need
# finer granularity than the standard preprocessor definitions offer.
# This generated include allow us to separate local builds from automated
# builds, separate beta from release, and use different UUIDs in downstream
# projects such as Thunderbird.
CONFIGURE_SUBST_FILES += ["HandlerDataUUID.h"]
flags = []
GeneratedFile(
"HandlerData.h",
"HandlerData_p.c",
"HandlerData_i.c",
"HandlerData_c.c",
"HandlerData_dlldata.c",
"HandlerData.tlb",
inputs=["HandlerData.idl"],
script="/build/midl.py",
entry_point="midl",
flags=flags
+ [
"-I",
TOPOBJDIR,
"-I",
TOPOBJDIR + "/dist/include",
"-I",
TOPSRCDIR + "/other-licenses/ia2",
"-I",
SRCDIR,
"-I",
OBJDIR,
"-acf",
SRCDIR + "/HandlerData.acf",
"-dlldata",
OBJDIR + "/HandlerData_dlldata.c",
],
)
SOURCES += [
"!HandlerData_c.c",
"!HandlerData_dlldata.c",
"!HandlerData_i.c",
"!HandlerData_p.c",
"AccessibleHandler.cpp",
"AccessibleHandlerControl.cpp",
"HandlerChildEnumerator.cpp",
"HandlerRelation.cpp",
"HandlerTextLeaf.cpp",
]
EXPORTS += [
"!HandlerData.h",
"!HandlerData_i.c",
"!HandlerDataUUID.h",
]
# Give some symbols a unique name in each translation unit, to avoid
# collisions caused by https://llvm.org/pr41817.
if CONFIG["CC_TYPE"] == "clang-cl":
SOURCES["!HandlerData_p.c"].flags += [
"-DHandlerData__MIDL_ProcFormatString=HandlerData__MIDL_ProcFormatString__HandlerData_p"
]
SOURCES["!HandlerData_p.c"].flags += [
"-DHandlerData__MIDL_TypeFormatString=HandlerData__MIDL_TypeFormatString__HandlerData_p"
]
for p in ("dlldata", "c", "i", "p"):
SOURCES["!HandlerData_%s.c" % p].flags += [
"-DUserMarshalRoutines=UserMarshalRoutines__HandlerData_%s" % p
]
DEFFILE = "AccessibleHandler.def"
USE_LIBS += [
"mscom_oop",
]
OS_LIBS += [
"advapi32",
"uuid",
"rpcrt4",
"oleacc",
"user32",
]
RCINCLUDE = "AccessibleHandler.rc"
# Suppress warnings from the MIDL generated code.
if CONFIG["CC_TYPE"] == "clang-cl":
CFLAGS += [
"-Wno-extern-initializer",
"-Wno-incompatible-pointer-types",
"-Wno-missing-braces",
"-Wno-unused-const-variable",
]
# Since we are defining our own COM entry points (DllRegisterServer et al),
# but we still want to be able to delegate some work to the generated code,
# we add the prefix "Proxy" to all of the generated counterparts.
DEFINES["ENTRY_PREFIX"] = "Proxy"
DEFINES["REGISTER_PROXY_DLL"] = True
LIBRARY_DEFINES["MOZ_MSCOM_REMARSHAL_NO_HANDLER"] = True
# This DLL may be loaded into other processes, so we need static libs for
# Windows 7 and Windows 8.
USE_STATIC_LIBS = True
LIBRARY_DEFINES["UNICODE"] = True
LIBRARY_DEFINES["_UNICODE"] = True
LIBRARY_DEFINES["MOZ_NO_MOZALLOC"] = True
DisableStlWrapping()
DELAYLOAD_DLLS += [
"advapi32.dll",
"ktmw32.dll",
]

View File

@ -4,34 +4,18 @@
# 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 CONFIG["COMPILE_ENVIRONMENT"] and CONFIG["ACCESSIBILITY"]:
DIRS += [
"handler",
"typelib",
]
if CONFIG["ACCESSIBILITY"]:
IPDL_SOURCES += ["PDocAccessible.ipdl"]
EXPORTS.mozilla.a11y += [
"DocAccessibleChild.h",
"HandlerProvider.h",
"RemoteAccessible.h",
]
SOURCES += [
"!./handler/HandlerData_c.c",
"DocAccessibleChild.cpp",
"HandlerProvider.cpp",
]
# Give some symbols a unique name in each translation unit, to avoid
# collisions caused by https://llvm.org/pr41817.
if CONFIG["CC_TYPE"] == "clang-cl":
SOURCES["!./handler/HandlerData_c.c"].flags += [
"-DUserMarshalRoutines=UserMarshalRoutines__HandlerData_c"
]
LOCAL_INCLUDES += [
"/accessible/base",
"/accessible/generic",

View File

@ -1,15 +0,0 @@
/* -*- 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/. */
import "oaidl.idl";
import "servprov.idl";
[uuid(b4d37cda-0dac-45e6-b613-158a5eb94293)]
library Accessible
{
interface IEnumVARIANT;
interface IServiceProvider;
};

View File

@ -1,16 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; 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/.
FINAL_TARGET_FILES += [
"!Accessible.tlb",
]
GeneratedFile(
"Accessible.tlb",
inputs=["Accessible.idl"],
script="/build/midl.py",
entry_point="midl",
)

View File

@ -1,95 +0,0 @@
/* -*- 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 "AccessibleWrap.h"
#include "GeckoCustom.h"
using namespace mozilla;
using namespace mozilla::a11y;
IMPL_IUNKNOWN_QUERY_HEAD(GeckoCustom)
IMPL_IUNKNOWN_QUERY_IFACE(IGeckoCustom)
IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mMsaa)
HRESULT
GeckoCustom::get_anchorCount(long* aCount) {
AccessibleWrap* acc = mMsaa->LocalAcc();
if (!acc) {
return CO_E_OBJNOTCONNECTED;
}
*aCount = acc->AnchorCount();
return S_OK;
}
HRESULT
GeckoCustom::get_boundsInCSSPixels(int32_t* aX, int32_t* aY, int32_t* aWidth,
int32_t* aHeight) {
AccessibleWrap* acc = mMsaa->LocalAcc();
if (!acc) {
return CO_E_OBJNOTCONNECTED;
}
nsIntRect bounds = acc->BoundsInCSSPixels();
if (!bounds.IsEmpty()) {
*aWidth = bounds.Width();
*aHeight = bounds.Height();
}
// We should always report positional bounds info, even if
// our rect is empty.
*aX = bounds.X();
*aY = bounds.Y();
return S_OK;
}
HRESULT
GeckoCustom::get_DOMNodeID(BSTR* aID) {
AccessibleWrap* acc = mMsaa->LocalAcc();
if (!acc) {
return CO_E_OBJNOTCONNECTED;
}
nsIContent* content = acc->GetContent();
if (!content) {
return S_OK;
}
nsAtom* id = content->GetID();
if (id) {
nsAutoString idStr;
id->ToString(idStr);
*aID = ::SysAllocStringLen(idStr.get(), idStr.Length());
}
return S_OK;
}
STDMETHODIMP
GeckoCustom::get_ID(uint64_t* aID) {
AccessibleWrap* acc = mMsaa->LocalAcc();
if (!acc) {
return CO_E_OBJNOTCONNECTED;
}
*aID = acc->IsDoc() ? 0 : reinterpret_cast<uintptr_t>(acc);
return S_OK;
}
STDMETHODIMP
GeckoCustom::get_minimumIncrement(double* aIncrement) {
AccessibleWrap* acc = mMsaa->LocalAcc();
if (!acc) {
return CO_E_OBJNOTCONNECTED;
}
*aIncrement = acc->Step();
return S_OK;
}
STDMETHODIMP
GeckoCustom::get_mozState(uint64_t* aState) {
AccessibleWrap* acc = mMsaa->LocalAcc();
if (!acc) {
return CO_E_OBJNOTCONNECTED;
}
*aState = acc->State();
return S_OK;
}

View File

@ -1,52 +0,0 @@
/* -*- 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_GeckoCustom_h_
#define mozilla_a11y_GeckoCustom_h_
#include "IUnknownImpl.h"
#include "IGeckoCustom.h"
#include "MsaaAccessible.h"
namespace mozilla {
namespace a11y {
/**
* a dumpster to put things exposed by the xpcom API but not a windows platform
* API for the purposes of testing.
*/
class GeckoCustom final : public IGeckoCustom {
public:
explicit GeckoCustom(MsaaAccessible* aMsaa) : mMsaa(aMsaa) {}
// IUnknown
DECL_IUNKNOWN
virtual STDMETHODIMP get_anchorCount(long* aCount);
virtual STDMETHODIMP get_boundsInCSSPixels(int32_t* aX, int32_t* aY,
int32_t* aWidth, int32_t* aHeight);
virtual STDMETHODIMP get_DOMNodeID(BSTR* aID);
virtual STDMETHODIMP get_ID(uint64_t* aID);
virtual STDMETHODIMP get_minimumIncrement(double* aIncrement);
virtual STDMETHODIMP get_mozState(uint64_t* aState);
private:
GeckoCustom() = delete;
GeckoCustom& operator=(const GeckoCustom&) = delete;
GeckoCustom(const GeckoCustom&) = delete;
GeckoCustom(GeckoCustom&&) = delete;
GeckoCustom& operator=(GeckoCustom&&) = delete;
~GeckoCustom() {}
protected:
RefPtr<MsaaAccessible> mMsaa;
};
} // namespace a11y
} // namespace mozilla
#endif

View File

@ -8,7 +8,6 @@
#include "MainThreadUtils.h"
#include "mozilla/a11y/LocalAccessible.h"
#include "mozilla/a11y/AccessibleHandler.h"
#include "mozilla/a11y/Compatibility.h"
#include "mozilla/a11y/Platform.h"
#include "mozilla/Assertions.h"
@ -724,6 +723,26 @@ LazyInstantiator::put_accValue(VARIANT varChild, BSTR szValue) {
return E_NOTIMPL;
}
static const GUID kUnsupportedServices[] = {
// clang-format off
// Unknown, queried by Windows on devices with touch screens or similar devices
// connected.
{0x33f139ee, 0xe509, 0x47f7, {0xbf, 0x39, 0x83, 0x76, 0x44, 0xf7, 0x45, 0x76}},
// Unknown, queried by Windows
{0xFDA075CF, 0x7C8B, 0x498C, { 0xB5, 0x14, 0xA9, 0xCB, 0x52, 0x1B, 0xBF, 0xB4 }},
// 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 }},
// SID_IsUIAutomationObject (undocumented), queried by Windows
{0xb96fdb85, 0x7204, 0x4724, { 0x84, 0x2b, 0xc7, 0x05, 0x9d, 0xed, 0xb9, 0xd0 }},
// IIS_IsOleaccProxy (undocumented), queried by Windows
{0x902697FA, 0x80E4, 0x4560, {0x80, 0x2A, 0xA1, 0x3F, 0x22, 0xA6, 0x47, 0x09}},
// IID_IHTMLElement, queried by JAWS
{0x3050F1FF, 0x98B5, 0x11CF, {0xBB, 0x82, 0x00, 0xAA, 0x00, 0xBD, 0xCE, 0x0B}}
// clang-format on
};
HRESULT
LazyInstantiator::QueryService(REFGUID aServiceId, REFIID aServiceIid,
void** aOutInterface) {

View File

@ -123,11 +123,6 @@ void a11y::ProxySelectionEvent(RemoteAccessible* aTarget, RemoteAccessible*,
MsaaAccessible::FireWinEvent(aTarget, aType);
}
bool a11y::IsHandlerRegistered() {
// XXX This is no longer useful and will soon be removed.
return false;
}
static bool GetInstantiatorExecutable(const DWORD aPid,
nsIFile** aOutClientExe) {
nsAutoHandle callingProcess(

View File

@ -25,7 +25,6 @@ UNIFIED_SOURCES += [
"CompatibilityUIA.cpp",
"DocAccessibleWrap.cpp",
"EnumVariant.cpp",
"GeckoCustom.cpp",
"HyperTextAccessibleWrap.cpp",
"IUnknownImpl.cpp",
"MsaaAccessible.cpp",

View File

@ -5,9 +5,3 @@
MOZ_APP_DISPLAYNAME="Firefox Developer Edition"
MOZ_APP_REMOTINGNAME=firefox-dev
MOZ_DEV_EDITION=1
# Devedition builds - use same as release channel
MOZ_HANDLER_CLSID="1baa303d-b4b9-45e5-9ccb-e3fca3e274b6"
MOZ_IHANDLERCONTROL_IID="ce30f77e-8847-44f0-a648-a9656bd89c0d"
MOZ_ASYNCIHANDLERCONTROL_IID="dca8d857-1a63-4045-8f36-8809eb093d04"
MOZ_IGECKOBACKCHANNEL_IID="b32983ff-ef84-4945-8f86-fb7491b4f57b"

View File

@ -4,8 +4,3 @@
MOZ_APP_DISPLAYNAME="Firefox Nightly"
MOZ_MACBUNDLE_ID=nightly
MOZ_HANDLER_CLSID="4629216b-8753-41bf-9527-5bff51401671"
MOZ_IHANDLERCONTROL_IID="c57343fc-e011-40c2-b748-da82eabf0f1f"
MOZ_ASYNCIHANDLERCONTROL_IID="648c92a1-ea35-46da-a806-6b55c6247373"
MOZ_IGECKOBACKCHANNEL_IID="e61e038d-40dd-464a-9aba-66b206b6911b"

View File

@ -3,17 +3,3 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
MOZ_APP_DISPLAYNAME=Firefox
if test "$MOZ_UPDATE_CHANNEL" = "beta"; then
# Official beta builds
MOZ_HANDLER_CLSID="21e9f98d-a6c9-4cb5-b288-ae2fd2a96c58"
MOZ_IHANDLERCONTROL_IID="119149fa-d212-4f22-9517-082eecc1a084"
MOZ_ASYNCIHANDLERCONTROL_IID="4e253d9b-59cf-4b32-a973-38bc85495d61"
MOZ_IGECKOBACKCHANNEL_IID="77b75c7d-d1c2-4469-864d-31aaebb67cc6"
else
# Official release/esr builds
MOZ_HANDLER_CLSID="1baa303d-b4b9-45e5-9ccb-e3fca3e274b6"
MOZ_IHANDLERCONTROL_IID="ce30f77e-8847-44f0-a648-a9656bd89c0d"
MOZ_ASYNCIHANDLERCONTROL_IID="dca8d857-1a63-4045-8f36-8809eb093d04"
MOZ_IGECKOBACKCHANNEL_IID="b32983ff-ef84-4945-8f86-fb7491b4f57b"
fi

View File

@ -3,19 +3,3 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
MOZ_APP_DISPLAYNAME=Nightly
if test "$DEVELOPER_OPTIONS"; then
if test "$MOZ_DEBUG"; then
# Local debug builds
MOZ_HANDLER_CLSID="398ffd8d-5382-48f7-9e3b-19012762d39a"
MOZ_IHANDLERCONTROL_IID="a218497e-8b10-460b-b668-a92b7ee39ff2"
MOZ_ASYNCIHANDLERCONTROL_IID="ca18b9ab-04b6-41be-87f7-d99913d6a2e8"
MOZ_IGECKOBACKCHANNEL_IID="231c4946-4479-4c8e-aadc-8a0e48fc4c51"
else
# Local non-debug builds
MOZ_HANDLER_CLSID="ce573faf-7815-4fc2-a031-b092268ace9e"
MOZ_IHANDLERCONTROL_IID="2b715cce-1790-4fe1-aef5-48bb5acdf3a1"
MOZ_ASYNCIHANDLERCONTROL_IID="8e089670-4f57-41a7-89c0-37f17482fa6f"
MOZ_IGECKOBACKCHANNEL_IID="18e2488d-310f-400f-8339-0e50b513e801"
fi
fi

View File

@ -5,11 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <utility>
#if defined(ACCESSIBILITY)
# include "HandlerData.h"
# include "mozilla/a11y/Platform.h"
# include "mozilla/mscom/ActivationContext.h"
#endif // defined(ACCESSIBILITY)
#include "mozilla/mscom/EnsureMTA.h"
#include "mozilla/mscom/ProxyStream.h"
#include "mozilla/mscom/Utils.h"
@ -67,25 +62,13 @@ ProxyStream::ProxyStream(REFIID aIID, const BYTE* aInitBuf,
return;
}
#if defined(ACCESSIBILITY)
const uint32_t expectedStreamLen = GetOBJREFSize(WrapNotNull(mStream));
nsAutoCString strActCtx;
nsAutoString manifestPath;
#endif // defined(ACCESSIBILITY)
HRESULT unmarshalResult = S_OK;
// We need to convert to an interface here otherwise we mess up const
// correctness with IPDL. We'll request an IUnknown and then QI the
// actual interface later.
#if defined(ACCESSIBILITY)
auto marshalFn = [this, &strActCtx, &manifestPath, &unmarshalResult, &aIID,
aEnv]() -> void
#else
auto marshalFn = [this, &unmarshalResult, &aIID, aEnv]() -> void
#endif // defined(ACCESSIBILITY)
{
auto marshalFn = [this, &unmarshalResult, &aIID, aEnv]() -> void {
if (aEnv) {
bool pushOk = aEnv->Push();
MOZ_DIAGNOSTIC_ASSERT(pushOk);
@ -106,17 +89,6 @@ ProxyStream::ProxyStream(REFIID aIID, const BYTE* aInitBuf,
MOZ_DIAGNOSTIC_ASSERT(popOk);
});
#if defined(ACCESSIBILITY)
auto curActCtx = ActivationContext::GetCurrent();
if (curActCtx.isOk()) {
strActCtx.AppendPrintf("0x%" PRIxPTR, curActCtx.unwrap());
} else {
strActCtx.AppendPrintf("HRESULT 0x%08lX", curActCtx.unwrapErr());
}
ActivationContext::GetCurrentManifestPath(manifestPath);
#endif // defined(ACCESSIBILITY)
unmarshalResult = ::CoUnmarshalInterface(mStream, aIID,
getter_AddRefs(mUnmarshaledProxy));
MOZ_ASSERT(SUCCEEDED(unmarshalResult));
@ -142,24 +114,6 @@ ProxyStream::ProxyStream(REFIID aIID, const BYTE* aInitBuf,
CrashReporter::AnnotateCrashReport(kCrashReportKey,
"!mUnmarshaledProxy"_ns);
}
#if defined(ACCESSIBILITY)
AnnotateClassRegistration(CLSID_AccessibleHandler);
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::UnmarshalActCtx, strActCtx);
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::UnmarshalActCtxManifestPath,
NS_ConvertUTF16toUTF8(manifestPath));
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::A11yHandlerRegistered,
a11y::IsHandlerRegistered() ? "true"_ns : "false"_ns);
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::ExpectedStreamLen, expectedStreamLen);
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::ActualStreamLen, aInitBufSize);
#endif // defined(ACCESSIBILITY)
}
}
@ -281,16 +235,9 @@ ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject, Environment* aEnv,
HRESULT statResult = S_OK;
HRESULT getHGlobalResult = S_OK;
#if defined(ACCESSIBILITY)
nsAutoString manifestPath;
auto marshalFn = [&aIID, aObject, mshlFlags, &stream, &streamSize, &hglobal,
&createStreamResult, &marshalResult, &statResult,
&getHGlobalResult, aEnv, &manifestPath]() -> void {
#else
auto marshalFn = [&aIID, aObject, mshlFlags, &stream, &streamSize, &hglobal,
&createStreamResult, &marshalResult, &statResult,
&getHGlobalResult, aEnv]() -> void {
#endif // defined(ACCESSIBILITY)
if (aEnv) {
bool pushOk = aEnv->Push();
MOZ_DIAGNOSTIC_ASSERT(pushOk);
@ -317,10 +264,6 @@ ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject, Environment* aEnv,
return;
}
#if defined(ACCESSIBILITY)
ActivationContext::GetCurrentManifestPath(manifestPath);
#endif // defined(ACCESSIBILITY)
marshalResult = ::CoMarshalInterface(stream, aIID, aObject, MSHCTX_LOCAL,
nullptr, mshlFlags);
MOZ_ASSERT(marshalResult != E_INVALIDARG);
@ -360,11 +303,6 @@ ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject, Environment* aEnv,
nsPrintfCString hrAsStr("0x%08lX", marshalResult);
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::CoMarshalInterfaceFailure, hrAsStr);
#if defined(ACCESSIBILITY)
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::MarshalActCtxManifestPath,
NS_ConvertUTF16toUTF8(manifestPath));
#endif // defined(ACCESSIBILITY)
}
if (FAILED(statResult)) {

View File

@ -1343,21 +1343,6 @@ if test -n "$MOZ_DEV_EDITION"; then
AC_DEFINE(MOZ_DEV_EDITION)
fi
dnl Windows AccessibilityHandler
dnl ========================================================
if test -z "$MOZ_HANDLER_CLSID"; then
MOZ_HANDLER_CLSID="4a195748-dca2-45fb-9295-0a139e76a9e7"
MOZ_IHANDLERCONTROL_IID="3316ce35-f892-4832-97c5-06c52c03cdba"
MOZ_ASYNCIHANDLERCONTROL_IID="15b48b76-ad38-4ad3-bd1a-d3c48a5a9947"
MOZ_IGECKOBACKCHANNEL_IID="dd2e4a89-999e-4d65-8b65-440c923ddb61"
fi
AC_SUBST(MOZ_HANDLER_CLSID)
AC_SUBST(MOZ_IHANDLERCONTROL_IID)
AC_SUBST(MOZ_ASYNCIHANDLERCONTROL_IID)
AC_SUBST(MOZ_IGECKOBACKCHANNEL_IID)
dnl Spit out some output
dnl ========================================================

View File

@ -1132,11 +1132,6 @@ var snapshotFormatters = {
$("a11y-activated").textContent = data.isActive;
$("a11y-force-disabled").textContent = data.forceDisabled || 0;
let a11yHandlerUsed = $("a11y-handler-used");
if (a11yHandlerUsed) {
a11yHandlerUsed.textContent = data.handlerUsed;
}
let a11yInstantiator = $("a11y-instantiator");
if (a11yInstantiator) {
a11yInstantiator.textContent = data.instantiator;

View File

@ -691,13 +691,6 @@
</td>
</tr>
#if defined(XP_WIN)
<tr>
<th class="column" data-l10n-id="a11y-handler-used"/>
<td id="a11y-handler-used">
</td>
</tr>
<tr>
<th class="column" data-l10n-id="a11y-instantiator"/>

View File

@ -11,11 +11,6 @@
# - ping: A boolean that indicates whether the annotation is allowlisted for
# going into the crash ping, if not specified this defaults to false
A11yHandlerRegistered:
description: >
Set to "true" if the accessibility handler is registered, "false" otherwise.
type: string
AbortMessage:
description: >
Message passed to NS_DebugBreak().
@ -37,11 +32,6 @@ AccessibilityInProcClient:
accessible/windows/msaa/Compatibility.h for the mappings.
type: string
ActualStreamLen:
description: >
Actual length of an IPC proxy stream.
type: integer
AdapterDeviceID:
description: >
Graphics adapter name.
@ -302,11 +292,6 @@ EventLoopNestingLevel:
type: integer
ping: true
ExpectedStreamLen:
description: >
Expected length of an IPC proxy stream.
type: integer
ExperimentalFeatures:
description: >
Comma-separated list of enabled experimental features from about:preferences#experimental.
@ -663,11 +648,6 @@ MainThreadRunnableName:
type: string
ping: true
MarshalActCtxManifestPath:
description: >
Proxy stream marshalling current activation context manifest path.
type: string
MozCrashReason:
description: >
Plaintext description of why Firefox crashed, this is usually set by
@ -968,16 +948,6 @@ UnknownNetAddrSocketFamily:
requested family number.
type: integer
UnmarshalActCtx:
description: >
Proxy stream unmarshalling current activation context.
type: string
UnmarshalActCtxManifestPath:
description: >
Proxy stream unmarshalling current activation context manifest path.
type: string
UptimeTS:
description: >
Uptime in seconds. This annotation uses a string instead of an integer

View File

@ -4,6 +4,3 @@
#include "mozilla-config.h"
#include "widget.rc"
#ifdef ACCESSIBILITY
1 typelib IGeckoCustom.tlb
#endif

View File

@ -892,7 +892,6 @@ var dataProviders = {
"accessibility.force_disabled"
);
} catch (e) {}
data.handlerUsed = Services.appinfo.accessibleHandlerUsed;
data.instantiator = Services.appinfo.accessibilityInstantiator;
done(data);
},

View File

@ -1463,17 +1463,6 @@ nsXULAppInfo::GetAccessibilityEnabled(bool* aResult) {
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetAccessibleHandlerUsed(bool* aResult) {
#if defined(ACCESSIBILITY) && defined(XP_WIN)
*aResult = Preferences::GetBool("accessibility.handler.enabled", false) &&
a11y::IsHandlerRegistered();
#else
*aResult = false;
#endif
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetAccessibilityInstantiator(nsAString& aInstantiator) {
#if defined(ACCESSIBILITY) && defined(XP_WIN)

View File

@ -267,11 +267,6 @@ interface nsIXULRuntime : nsISupports
*/
readonly attribute boolean accessibilityEnabled;
/**
* If true, the AccessibleHandler dll is used.
*/
readonly attribute boolean accessibleHandlerUsed;
/**
* Executable of Windows service that activated accessibility.
*/