mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
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:
parent
13afc4eeb2
commit
3a3b50114d
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
};
|
@ -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",
|
||||
]
|
@ -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
|
||||
|
@ -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>
|
@ -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
|
@ -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"
|
@ -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",
|
||||
]
|
||||
|
@ -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"]
|
||||
|
@ -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
|
@ -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
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
@ -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;
|
||||
};
|
||||
};
|
@ -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
|
@ -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@
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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",
|
||||
]
|
@ -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",
|
||||
|
@ -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;
|
||||
};
|
@ -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",
|
||||
)
|
@ -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;
|
||||
}
|
@ -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
|
@ -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) {
|
||||
|
@ -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(
|
||||
|
@ -25,7 +25,6 @@ UNIFIED_SOURCES += [
|
||||
"CompatibilityUIA.cpp",
|
||||
"DocAccessibleWrap.cpp",
|
||||
"EnumVariant.cpp",
|
||||
"GeckoCustom.cpp",
|
||||
"HyperTextAccessibleWrap.cpp",
|
||||
"IUnknownImpl.cpp",
|
||||
"MsaaAccessible.cpp",
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)) {
|
||||
|
@ -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 ========================================================
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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"/>
|
||||
|
||||
|
@ -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
|
||||
|
@ -4,6 +4,3 @@
|
||||
|
||||
#include "mozilla-config.h"
|
||||
#include "widget.rc"
|
||||
#ifdef ACCESSIBILITY
|
||||
1 typelib IGeckoCustom.tlb
|
||||
#endif
|
||||
|
@ -892,7 +892,6 @@ var dataProviders = {
|
||||
"accessibility.force_disabled"
|
||||
);
|
||||
} catch (e) {}
|
||||
data.handlerUsed = Services.appinfo.accessibleHandlerUsed;
|
||||
data.instantiator = Services.appinfo.accessibilityInstantiator;
|
||||
done(data);
|
||||
},
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user