Bug 1303060: Changes to a11y to enable the serving of a COM handler; r=tbsaunde
MozReview-Commit-ID: GTQF3x1pBtX
A general outline of the COM handler (a.k.a. the "smart proxy"):
COM handlers are pieces of code that are loaded by the COM runtime along with
a proxy and are layered above that proxy. This enables the COM handler to
interpose itself between the caller and the proxy, thus providing the
opportunity for the handler to manipulate an interface's method calls before
those calls reach the proxy.
Handlers are regular COM components that live in DLLs and are declared in the
Windows registry. In order to allow for the specifying of a handler (and an
optional payload to be sent with the proxy), the mscom library allows its
clients to specify an implementation of the IHandlerProvider interface.
IHandlerProvider consists of 5 functions:
* GetHandler returns the CLSID of the component that should be loaded into
the COM client's process. If GetHandler returns a failure code, then no
handler is loaded.
* GetHandlerPayloadSize and WriteHandlerPayload are for obtaining the payload
data. These calls are made on a background thread but need to do their work
on the main thread. We declare the payload struct in IDL. MIDL generates two
functions, IA2Payload_Encode and IA2Payload_Decode, which are used by
mscom::StructToStream to read and write that struct to and from buffers.
* The a11y payload struct also includes an interface, IGeckoBackChannel, that
allows the handler to communicate directly with Gecko. IGeckoBackChannel
currently provides two methods: one to allow the handler to request fresh
cache information, and the other to provide Gecko with its IHandlerControl
interface.
* MarshalAs accepts an IID that specifies the interface that is about to be
proxied. We may want to send a more sophisticated proxy than the one that
is requested. The desired IID is returned by this function. In the case of
a11y interfaces, we should always return IAccessible2_3 if we are asked for
one of its parent interfaces. This allows us to eliminate round trips to
resolve more sophisticated interfaces later on.
* NewInstance, which is needed to ensure that all descendent proxies are also
imbued with the same handler code.
The main focus of this patch is as follows:
1. Provide an implementation of the IHandlerProvider interface;
2. Populate the handler payload (ie, the cache) with data;
3. Modify CreateHolderFromAccessible to specify the HandlerPayload object;
4. Receive the IHandlerControl interface from the handler DLL and move it
into the chrome process.
Some more information about IHandlerControl:
There is one IHandlerControl per handler DLL instance. It is the interface that
we call in Gecko when we need to dispatch an event to the handler. In order to
ensure that events are dispatched in the correct order, we need to dispatch
those events from the chrome main thread so that they occur in sequential order
with calls to NotifyWinEvent.
--HG--
extra : rebase_source : acb44dead7cc5488424720e1bf58862b7b30374f
2017-04-05 00:23:55 +03:00
|
|
|
/* -*- 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)
|
|
|
|
|
2018-12-25 20:49:23 +03:00
|
|
|
#if defined(__midl) || defined(__WIDL__)
|
Bug 1303060: Changes to a11y to enable the serving of a COM handler; r=tbsaunde
MozReview-Commit-ID: GTQF3x1pBtX
A general outline of the COM handler (a.k.a. the "smart proxy"):
COM handlers are pieces of code that are loaded by the COM runtime along with
a proxy and are layered above that proxy. This enables the COM handler to
interpose itself between the caller and the proxy, thus providing the
opportunity for the handler to manipulate an interface's method calls before
those calls reach the proxy.
Handlers are regular COM components that live in DLLs and are declared in the
Windows registry. In order to allow for the specifying of a handler (and an
optional payload to be sent with the proxy), the mscom library allows its
clients to specify an implementation of the IHandlerProvider interface.
IHandlerProvider consists of 5 functions:
* GetHandler returns the CLSID of the component that should be loaded into
the COM client's process. If GetHandler returns a failure code, then no
handler is loaded.
* GetHandlerPayloadSize and WriteHandlerPayload are for obtaining the payload
data. These calls are made on a background thread but need to do their work
on the main thread. We declare the payload struct in IDL. MIDL generates two
functions, IA2Payload_Encode and IA2Payload_Decode, which are used by
mscom::StructToStream to read and write that struct to and from buffers.
* The a11y payload struct also includes an interface, IGeckoBackChannel, that
allows the handler to communicate directly with Gecko. IGeckoBackChannel
currently provides two methods: one to allow the handler to request fresh
cache information, and the other to provide Gecko with its IHandlerControl
interface.
* MarshalAs accepts an IID that specifies the interface that is about to be
proxied. We may want to send a more sophisticated proxy than the one that
is requested. The desired IID is returned by this function. In the case of
a11y interfaces, we should always return IAccessible2_3 if we are asked for
one of its parent interfaces. This allows us to eliminate round trips to
resolve more sophisticated interfaces later on.
* NewInstance, which is needed to ensure that all descendent proxies are also
imbued with the same handler code.
The main focus of this patch is as follows:
1. Provide an implementation of the IHandlerProvider interface;
2. Populate the handler payload (ie, the cache) with data;
3. Modify CreateHolderFromAccessible to specify the HandlerPayload object;
4. Receive the IHandlerControl interface from the handler DLL and move it
into the chrome process.
Some more information about IHandlerControl:
There is one IHandlerControl per handler DLL instance. It is the interface that
we call in Gecko when we need to dispatch an event to the handler. In order to
ensure that events are dispatched in the correct order, we need to dispatch
those events from the chrome main thread so that they occur in sequential order
with calls to NotifyWinEvent.
--HG--
extra : rebase_source : acb44dead7cc5488424720e1bf58862b7b30374f
2017-04-05 00:23:55 +03:00
|
|
|
|
2019-03-26 19:29:17 +03:00
|
|
|
import "Accessible2_3.idl";
|
Bug 1303060: Changes to a11y to enable the serving of a COM handler; r=tbsaunde
MozReview-Commit-ID: GTQF3x1pBtX
A general outline of the COM handler (a.k.a. the "smart proxy"):
COM handlers are pieces of code that are loaded by the COM runtime along with
a proxy and are layered above that proxy. This enables the COM handler to
interpose itself between the caller and the proxy, thus providing the
opportunity for the handler to manipulate an interface's method calls before
those calls reach the proxy.
Handlers are regular COM components that live in DLLs and are declared in the
Windows registry. In order to allow for the specifying of a handler (and an
optional payload to be sent with the proxy), the mscom library allows its
clients to specify an implementation of the IHandlerProvider interface.
IHandlerProvider consists of 5 functions:
* GetHandler returns the CLSID of the component that should be loaded into
the COM client's process. If GetHandler returns a failure code, then no
handler is loaded.
* GetHandlerPayloadSize and WriteHandlerPayload are for obtaining the payload
data. These calls are made on a background thread but need to do their work
on the main thread. We declare the payload struct in IDL. MIDL generates two
functions, IA2Payload_Encode and IA2Payload_Decode, which are used by
mscom::StructToStream to read and write that struct to and from buffers.
* The a11y payload struct also includes an interface, IGeckoBackChannel, that
allows the handler to communicate directly with Gecko. IGeckoBackChannel
currently provides two methods: one to allow the handler to request fresh
cache information, and the other to provide Gecko with its IHandlerControl
interface.
* MarshalAs accepts an IID that specifies the interface that is about to be
proxied. We may want to send a more sophisticated proxy than the one that
is requested. The desired IID is returned by this function. In the case of
a11y interfaces, we should always return IAccessible2_3 if we are asked for
one of its parent interfaces. This allows us to eliminate round trips to
resolve more sophisticated interfaces later on.
* NewInstance, which is needed to ensure that all descendent proxies are also
imbued with the same handler code.
The main focus of this patch is as follows:
1. Provide an implementation of the IHandlerProvider interface;
2. Populate the handler payload (ie, the cache) with data;
3. Modify CreateHolderFromAccessible to specify the HandlerPayload object;
4. Receive the IHandlerControl interface from the handler DLL and move it
into the chrome process.
Some more information about IHandlerControl:
There is one IHandlerControl per handler DLL instance. It is the interface that
we call in Gecko when we need to dispatch an event to the handler. In order to
ensure that events are dispatched in the correct order, we need to dispatch
those events from the chrome main thread so that they occur in sequential order
with calls to NotifyWinEvent.
--HG--
extra : rebase_source : acb44dead7cc5488424720e1bf58862b7b30374f
2017-04-05 00:23:55 +03:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
# include "HandlerData.h"
|
|
|
|
|
|
|
|
# include <windows.h>
|
|
|
|
|
Bug 1303060: Implementation of the caching COM handler for a11y; r=tbsaunde
MozReview-Commit-ID: HkiIgDQURtK
The a11y COM handler consists of two classes. AccessibleHandler is the one that
is actually interposed by COM between the client and the proxy. It implements
IAccessible2_3, IServiceProvider, and IProvideClassInfo. It is derived from
mscom::Handler which takes care of most of the COM boilerplate for handler
instantiation. AccessibleHandler must override a few virtual functions from
mscom::Handler:
* QueryHandlerInterface - mscom::Handler must implement the "real" QI. This is
the method that mscom::Handler uses to delegate to the implementer.
* ReadHandlerPayload - deserializing the payload. This uses
mscom::StructFromStream and the IA2Data_Decode function that was generated by
midl. It should essentially be the inverse of the serialization code in the
IHandlerProvider implementation inside Gecko.
* MarshalAs - identical to IHandlerProvider::MarshalAs
* GetHandlerPayloadSize and WriteHandlerPayload - it sucks that we have to
include these, but they are neccessary for the scenario when COM wants to
make a proxy of a proxy. When that happens, we need to get COM to serialize
the payload again; it isn't smart enough to recognize payloads in existing
proxies and copy them itself.
In order to reduce round trips, AccessibleHandler implements the most
sophisticated IA2 interface. This way the client has access to any of those
interfaces from IDispatch all the way down to IAccessible2_3 without needing to
incur additional round-trips to obtain them.
We also implement IServiceProvider so that a client may QueryService for an IA2
interface without needing to incur more round trips. In addition, we maintain
a list of service IDs that we definitely do not support, and handle those
locally instead of incurring an IPC round-trip.
We also implement IProvideClassInfo because NVDA's python code (and presumably
other ATs that use interpreted languages) supports using that interface to
assist its FFI library with resolution of our COM objects.
COM wraps each instance of an IAccessible* proxy with an AccessibleHandler
object. Proxies whose interfaces are not part of the IDispatch ... IAccessible2_3
hierarchy are not wrapped with handlers (though this might change in the future
if we need to expand coverage). AccessibleHandler implements IAccessible2_3 such
that, if we have cached data available for a particular IA2 method, we provide
that cached data to the client. Otherwise we pass on the request to the COM
proxy for retrieval via IPC.
The other class in the handler dll is AccessibleHandlerControl. This class
implements the IHandlerControl interface that is provided to IGeckoBackChannel.
Gecko dispatches cache invalidation events using this interface. This class
is a singleton within the handler dll and manages shared, handler-wide resources.
--HG--
extra : rebase_source : 4fc3910f789b0ed92c90655344ffb89f576ca5bd
2017-03-28 04:13:34 +03:00
|
|
|
# if !defined(MOZILLA_INTERNAL_API)
|
|
|
|
|
|
|
|
# include "Accessible2_3.h"
|
2017-10-13 10:01:20 +03:00
|
|
|
# include "AccessibleHyperlink.h"
|
2017-11-22 05:16:18 +03:00
|
|
|
# include "AccessibleHypertext2.h"
|
2017-11-16 04:47:28 +03:00
|
|
|
# include "AccessibleTableCell.h"
|
Bug 1303060: Implementation of the caching COM handler for a11y; r=tbsaunde
MozReview-Commit-ID: HkiIgDQURtK
The a11y COM handler consists of two classes. AccessibleHandler is the one that
is actually interposed by COM between the client and the proxy. It implements
IAccessible2_3, IServiceProvider, and IProvideClassInfo. It is derived from
mscom::Handler which takes care of most of the COM boilerplate for handler
instantiation. AccessibleHandler must override a few virtual functions from
mscom::Handler:
* QueryHandlerInterface - mscom::Handler must implement the "real" QI. This is
the method that mscom::Handler uses to delegate to the implementer.
* ReadHandlerPayload - deserializing the payload. This uses
mscom::StructFromStream and the IA2Data_Decode function that was generated by
midl. It should essentially be the inverse of the serialization code in the
IHandlerProvider implementation inside Gecko.
* MarshalAs - identical to IHandlerProvider::MarshalAs
* GetHandlerPayloadSize and WriteHandlerPayload - it sucks that we have to
include these, but they are neccessary for the scenario when COM wants to
make a proxy of a proxy. When that happens, we need to get COM to serialize
the payload again; it isn't smart enough to recognize payloads in existing
proxies and copy them itself.
In order to reduce round trips, AccessibleHandler implements the most
sophisticated IA2 interface. This way the client has access to any of those
interfaces from IDispatch all the way down to IAccessible2_3 without needing to
incur additional round-trips to obtain them.
We also implement IServiceProvider so that a client may QueryService for an IA2
interface without needing to incur more round trips. In addition, we maintain
a list of service IDs that we definitely do not support, and handle those
locally instead of incurring an IPC round-trip.
We also implement IProvideClassInfo because NVDA's python code (and presumably
other ATs that use interpreted languages) supports using that interface to
assist its FFI library with resolution of our COM objects.
COM wraps each instance of an IAccessible* proxy with an AccessibleHandler
object. Proxies whose interfaces are not part of the IDispatch ... IAccessible2_3
hierarchy are not wrapped with handlers (though this might change in the future
if we need to expand coverage). AccessibleHandler implements IAccessible2_3 such
that, if we have cached data available for a particular IA2 method, we provide
that cached data to the client. Otherwise we pass on the request to the COM
proxy for retrieval via IPC.
The other class in the handler dll is AccessibleHandlerControl. This class
implements the IHandlerControl interface that is provided to IGeckoBackChannel.
Gecko dispatches cache invalidation events using this interface. This class
is a singleton within the handler dll and manages shared, handler-wide resources.
--HG--
extra : rebase_source : 4fc3910f789b0ed92c90655344ffb89f576ca5bd
2017-03-28 04:13:34 +03:00
|
|
|
# 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,
|
2017-10-13 10:01:20 +03:00
|
|
|
public IAccessibleHyperlink,
|
2017-11-16 04:47:28 +03:00
|
|
|
public IAccessibleTableCell,
|
2017-11-22 05:16:18 +03:00
|
|
|
public IAccessibleHypertext2 {
|
Bug 1303060: Implementation of the caching COM handler for a11y; r=tbsaunde
MozReview-Commit-ID: HkiIgDQURtK
The a11y COM handler consists of two classes. AccessibleHandler is the one that
is actually interposed by COM between the client and the proxy. It implements
IAccessible2_3, IServiceProvider, and IProvideClassInfo. It is derived from
mscom::Handler which takes care of most of the COM boilerplate for handler
instantiation. AccessibleHandler must override a few virtual functions from
mscom::Handler:
* QueryHandlerInterface - mscom::Handler must implement the "real" QI. This is
the method that mscom::Handler uses to delegate to the implementer.
* ReadHandlerPayload - deserializing the payload. This uses
mscom::StructFromStream and the IA2Data_Decode function that was generated by
midl. It should essentially be the inverse of the serialization code in the
IHandlerProvider implementation inside Gecko.
* MarshalAs - identical to IHandlerProvider::MarshalAs
* GetHandlerPayloadSize and WriteHandlerPayload - it sucks that we have to
include these, but they are neccessary for the scenario when COM wants to
make a proxy of a proxy. When that happens, we need to get COM to serialize
the payload again; it isn't smart enough to recognize payloads in existing
proxies and copy them itself.
In order to reduce round trips, AccessibleHandler implements the most
sophisticated IA2 interface. This way the client has access to any of those
interfaces from IDispatch all the way down to IAccessible2_3 without needing to
incur additional round-trips to obtain them.
We also implement IServiceProvider so that a client may QueryService for an IA2
interface without needing to incur more round trips. In addition, we maintain
a list of service IDs that we definitely do not support, and handle those
locally instead of incurring an IPC round-trip.
We also implement IProvideClassInfo because NVDA's python code (and presumably
other ATs that use interpreted languages) supports using that interface to
assist its FFI library with resolution of our COM objects.
COM wraps each instance of an IAccessible* proxy with an AccessibleHandler
object. Proxies whose interfaces are not part of the IDispatch ... IAccessible2_3
hierarchy are not wrapped with handlers (though this might change in the future
if we need to expand coverage). AccessibleHandler implements IAccessible2_3 such
that, if we have cached data available for a particular IA2 method, we provide
that cached data to the client. Otherwise we pass on the request to the COM
proxy for retrieval via IPC.
The other class in the handler dll is AccessibleHandlerControl. This class
implements the IHandlerControl interface that is provided to IGeckoBackChannel.
Gecko dispatches cache invalidation events using this interface. This class
is a singleton within the handler dll and manages shared, handler-wide resources.
--HG--
extra : rebase_source : 4fc3910f789b0ed92c90655344ffb89f576ca5bd
2017-03-28 04:13:34 +03:00
|
|
|
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;
|
2017-09-24 23:32:36 +03:00
|
|
|
HRESULT GetMarshalInterface(REFIID aMarshalAsIid, NotNull<IUnknown*> aProxy,
|
|
|
|
NotNull<IID*> aOutIid,
|
|
|
|
NotNull<IUnknown**> aOutUnk) override;
|
Bug 1303060: Implementation of the caching COM handler for a11y; r=tbsaunde
MozReview-Commit-ID: HkiIgDQURtK
The a11y COM handler consists of two classes. AccessibleHandler is the one that
is actually interposed by COM between the client and the proxy. It implements
IAccessible2_3, IServiceProvider, and IProvideClassInfo. It is derived from
mscom::Handler which takes care of most of the COM boilerplate for handler
instantiation. AccessibleHandler must override a few virtual functions from
mscom::Handler:
* QueryHandlerInterface - mscom::Handler must implement the "real" QI. This is
the method that mscom::Handler uses to delegate to the implementer.
* ReadHandlerPayload - deserializing the payload. This uses
mscom::StructFromStream and the IA2Data_Decode function that was generated by
midl. It should essentially be the inverse of the serialization code in the
IHandlerProvider implementation inside Gecko.
* MarshalAs - identical to IHandlerProvider::MarshalAs
* GetHandlerPayloadSize and WriteHandlerPayload - it sucks that we have to
include these, but they are neccessary for the scenario when COM wants to
make a proxy of a proxy. When that happens, we need to get COM to serialize
the payload again; it isn't smart enough to recognize payloads in existing
proxies and copy them itself.
In order to reduce round trips, AccessibleHandler implements the most
sophisticated IA2 interface. This way the client has access to any of those
interfaces from IDispatch all the way down to IAccessible2_3 without needing to
incur additional round-trips to obtain them.
We also implement IServiceProvider so that a client may QueryService for an IA2
interface without needing to incur more round trips. In addition, we maintain
a list of service IDs that we definitely do not support, and handle those
locally instead of incurring an IPC round-trip.
We also implement IProvideClassInfo because NVDA's python code (and presumably
other ATs that use interpreted languages) supports using that interface to
assist its FFI library with resolution of our COM objects.
COM wraps each instance of an IAccessible* proxy with an AccessibleHandler
object. Proxies whose interfaces are not part of the IDispatch ... IAccessible2_3
hierarchy are not wrapped with handlers (though this might change in the future
if we need to expand coverage). AccessibleHandler implements IAccessible2_3 such
that, if we have cached data available for a particular IA2 method, we provide
that cached data to the client. Otherwise we pass on the request to the COM
proxy for retrieval via IPC.
The other class in the handler dll is AccessibleHandlerControl. This class
implements the IHandlerControl interface that is provided to IGeckoBackChannel.
Gecko dispatches cache invalidation events using this interface. This class
is a singleton within the handler dll and manages shared, handler-wide resources.
--HG--
extra : rebase_source : 4fc3910f789b0ed92c90655344ffb89f576ca5bd
2017-03-28 04:13:34 +03:00
|
|
|
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;
|
|
|
|
|
2017-10-13 10:01:20 +03:00
|
|
|
// 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;
|
|
|
|
|
2017-11-16 04:47:28 +03:00
|
|
|
// 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;
|
|
|
|
|
2017-11-22 05:16:18 +03:00
|
|
|
// 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;
|
|
|
|
|
Bug 1303060: Implementation of the caching COM handler for a11y; r=tbsaunde
MozReview-Commit-ID: HkiIgDQURtK
The a11y COM handler consists of two classes. AccessibleHandler is the one that
is actually interposed by COM between the client and the proxy. It implements
IAccessible2_3, IServiceProvider, and IProvideClassInfo. It is derived from
mscom::Handler which takes care of most of the COM boilerplate for handler
instantiation. AccessibleHandler must override a few virtual functions from
mscom::Handler:
* QueryHandlerInterface - mscom::Handler must implement the "real" QI. This is
the method that mscom::Handler uses to delegate to the implementer.
* ReadHandlerPayload - deserializing the payload. This uses
mscom::StructFromStream and the IA2Data_Decode function that was generated by
midl. It should essentially be the inverse of the serialization code in the
IHandlerProvider implementation inside Gecko.
* MarshalAs - identical to IHandlerProvider::MarshalAs
* GetHandlerPayloadSize and WriteHandlerPayload - it sucks that we have to
include these, but they are neccessary for the scenario when COM wants to
make a proxy of a proxy. When that happens, we need to get COM to serialize
the payload again; it isn't smart enough to recognize payloads in existing
proxies and copy them itself.
In order to reduce round trips, AccessibleHandler implements the most
sophisticated IA2 interface. This way the client has access to any of those
interfaces from IDispatch all the way down to IAccessible2_3 without needing to
incur additional round-trips to obtain them.
We also implement IServiceProvider so that a client may QueryService for an IA2
interface without needing to incur more round trips. In addition, we maintain
a list of service IDs that we definitely do not support, and handle those
locally instead of incurring an IPC round-trip.
We also implement IProvideClassInfo because NVDA's python code (and presumably
other ATs that use interpreted languages) supports using that interface to
assist its FFI library with resolution of our COM objects.
COM wraps each instance of an IAccessible* proxy with an AccessibleHandler
object. Proxies whose interfaces are not part of the IDispatch ... IAccessible2_3
hierarchy are not wrapped with handlers (though this might change in the future
if we need to expand coverage). AccessibleHandler implements IAccessible2_3 such
that, if we have cached data available for a particular IA2 method, we provide
that cached data to the client. Otherwise we pass on the request to the COM
proxy for retrieval via IPC.
The other class in the handler dll is AccessibleHandlerControl. This class
implements the IHandlerControl interface that is provided to IGeckoBackChannel.
Gecko dispatches cache invalidation events using this interface. This class
is a singleton within the handler dll and manages shared, handler-wide resources.
--HG--
extra : rebase_source : 4fc3910f789b0ed92c90655344ffb89f576ca5bd
2017-03-28 04:13:34 +03:00
|
|
|
private:
|
|
|
|
AccessibleHandler(IUnknown* aOuter, HRESULT* aResult);
|
|
|
|
virtual ~AccessibleHandler();
|
|
|
|
|
|
|
|
HRESULT ResolveIA2();
|
|
|
|
HRESULT ResolveIDispatch();
|
2017-10-13 10:01:20 +03:00
|
|
|
HRESULT ResolveIAHyperlink();
|
2017-11-22 05:16:18 +03:00
|
|
|
HRESULT ResolveIAHypertext();
|
2017-11-16 04:47:28 +03:00
|
|
|
HRESULT ResolveIATableCell();
|
Bug 1303060: Implementation of the caching COM handler for a11y; r=tbsaunde
MozReview-Commit-ID: HkiIgDQURtK
The a11y COM handler consists of two classes. AccessibleHandler is the one that
is actually interposed by COM between the client and the proxy. It implements
IAccessible2_3, IServiceProvider, and IProvideClassInfo. It is derived from
mscom::Handler which takes care of most of the COM boilerplate for handler
instantiation. AccessibleHandler must override a few virtual functions from
mscom::Handler:
* QueryHandlerInterface - mscom::Handler must implement the "real" QI. This is
the method that mscom::Handler uses to delegate to the implementer.
* ReadHandlerPayload - deserializing the payload. This uses
mscom::StructFromStream and the IA2Data_Decode function that was generated by
midl. It should essentially be the inverse of the serialization code in the
IHandlerProvider implementation inside Gecko.
* MarshalAs - identical to IHandlerProvider::MarshalAs
* GetHandlerPayloadSize and WriteHandlerPayload - it sucks that we have to
include these, but they are neccessary for the scenario when COM wants to
make a proxy of a proxy. When that happens, we need to get COM to serialize
the payload again; it isn't smart enough to recognize payloads in existing
proxies and copy them itself.
In order to reduce round trips, AccessibleHandler implements the most
sophisticated IA2 interface. This way the client has access to any of those
interfaces from IDispatch all the way down to IAccessible2_3 without needing to
incur additional round-trips to obtain them.
We also implement IServiceProvider so that a client may QueryService for an IA2
interface without needing to incur more round trips. In addition, we maintain
a list of service IDs that we definitely do not support, and handle those
locally instead of incurring an IPC round-trip.
We also implement IProvideClassInfo because NVDA's python code (and presumably
other ATs that use interpreted languages) supports using that interface to
assist its FFI library with resolution of our COM objects.
COM wraps each instance of an IAccessible* proxy with an AccessibleHandler
object. Proxies whose interfaces are not part of the IDispatch ... IAccessible2_3
hierarchy are not wrapped with handlers (though this might change in the future
if we need to expand coverage). AccessibleHandler implements IAccessible2_3 such
that, if we have cached data available for a particular IA2 method, we provide
that cached data to the client. Otherwise we pass on the request to the COM
proxy for retrieval via IPC.
The other class in the handler dll is AccessibleHandlerControl. This class
implements the IHandlerControl interface that is provided to IGeckoBackChannel.
Gecko dispatches cache invalidation events using this interface. This class
is a singleton within the handler dll and manages shared, handler-wide resources.
--HG--
extra : rebase_source : 4fc3910f789b0ed92c90655344ffb89f576ca5bd
2017-03-28 04:13:34 +03:00
|
|
|
HRESULT MaybeUpdateCachedData();
|
2017-11-22 14:32:28 +03:00
|
|
|
HRESULT GetAllTextInfo(BSTR* aText);
|
|
|
|
void ClearTextCache();
|
2018-02-02 02:38:51 +03:00
|
|
|
HRESULT GetRelationsInfo();
|
|
|
|
void ClearRelationCache();
|
Bug 1303060: Implementation of the caching COM handler for a11y; r=tbsaunde
MozReview-Commit-ID: HkiIgDQURtK
The a11y COM handler consists of two classes. AccessibleHandler is the one that
is actually interposed by COM between the client and the proxy. It implements
IAccessible2_3, IServiceProvider, and IProvideClassInfo. It is derived from
mscom::Handler which takes care of most of the COM boilerplate for handler
instantiation. AccessibleHandler must override a few virtual functions from
mscom::Handler:
* QueryHandlerInterface - mscom::Handler must implement the "real" QI. This is
the method that mscom::Handler uses to delegate to the implementer.
* ReadHandlerPayload - deserializing the payload. This uses
mscom::StructFromStream and the IA2Data_Decode function that was generated by
midl. It should essentially be the inverse of the serialization code in the
IHandlerProvider implementation inside Gecko.
* MarshalAs - identical to IHandlerProvider::MarshalAs
* GetHandlerPayloadSize and WriteHandlerPayload - it sucks that we have to
include these, but they are neccessary for the scenario when COM wants to
make a proxy of a proxy. When that happens, we need to get COM to serialize
the payload again; it isn't smart enough to recognize payloads in existing
proxies and copy them itself.
In order to reduce round trips, AccessibleHandler implements the most
sophisticated IA2 interface. This way the client has access to any of those
interfaces from IDispatch all the way down to IAccessible2_3 without needing to
incur additional round-trips to obtain them.
We also implement IServiceProvider so that a client may QueryService for an IA2
interface without needing to incur more round trips. In addition, we maintain
a list of service IDs that we definitely do not support, and handle those
locally instead of incurring an IPC round-trip.
We also implement IProvideClassInfo because NVDA's python code (and presumably
other ATs that use interpreted languages) supports using that interface to
assist its FFI library with resolution of our COM objects.
COM wraps each instance of an IAccessible* proxy with an AccessibleHandler
object. Proxies whose interfaces are not part of the IDispatch ... IAccessible2_3
hierarchy are not wrapped with handlers (though this might change in the future
if we need to expand coverage). AccessibleHandler implements IAccessible2_3 such
that, if we have cached data available for a particular IA2 method, we provide
that cached data to the client. Otherwise we pass on the request to the COM
proxy for retrieval via IPC.
The other class in the handler dll is AccessibleHandlerControl. This class
implements the IHandlerControl interface that is provided to IGeckoBackChannel.
Gecko dispatches cache invalidation events using this interface. This class
is a singleton within the handler dll and manages shared, handler-wide resources.
--HG--
extra : rebase_source : 4fc3910f789b0ed92c90655344ffb89f576ca5bd
2017-03-28 04:13:34 +03:00
|
|
|
|
|
|
|
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
|
2017-10-13 10:01:20 +03:00
|
|
|
IAccessibleHyperlink* mIAHyperlinkPassThru; // weak
|
2017-11-16 04:47:28 +03:00
|
|
|
IAccessibleTableCell* mIATableCellPassThru; // weak
|
2017-11-22 05:16:18 +03:00
|
|
|
IAccessibleHypertext2* mIAHypertextPassThru; // weak
|
Bug 1303060: Implementation of the caching COM handler for a11y; r=tbsaunde
MozReview-Commit-ID: HkiIgDQURtK
The a11y COM handler consists of two classes. AccessibleHandler is the one that
is actually interposed by COM between the client and the proxy. It implements
IAccessible2_3, IServiceProvider, and IProvideClassInfo. It is derived from
mscom::Handler which takes care of most of the COM boilerplate for handler
instantiation. AccessibleHandler must override a few virtual functions from
mscom::Handler:
* QueryHandlerInterface - mscom::Handler must implement the "real" QI. This is
the method that mscom::Handler uses to delegate to the implementer.
* ReadHandlerPayload - deserializing the payload. This uses
mscom::StructFromStream and the IA2Data_Decode function that was generated by
midl. It should essentially be the inverse of the serialization code in the
IHandlerProvider implementation inside Gecko.
* MarshalAs - identical to IHandlerProvider::MarshalAs
* GetHandlerPayloadSize and WriteHandlerPayload - it sucks that we have to
include these, but they are neccessary for the scenario when COM wants to
make a proxy of a proxy. When that happens, we need to get COM to serialize
the payload again; it isn't smart enough to recognize payloads in existing
proxies and copy them itself.
In order to reduce round trips, AccessibleHandler implements the most
sophisticated IA2 interface. This way the client has access to any of those
interfaces from IDispatch all the way down to IAccessible2_3 without needing to
incur additional round-trips to obtain them.
We also implement IServiceProvider so that a client may QueryService for an IA2
interface without needing to incur more round trips. In addition, we maintain
a list of service IDs that we definitely do not support, and handle those
locally instead of incurring an IPC round-trip.
We also implement IProvideClassInfo because NVDA's python code (and presumably
other ATs that use interpreted languages) supports using that interface to
assist its FFI library with resolution of our COM objects.
COM wraps each instance of an IAccessible* proxy with an AccessibleHandler
object. Proxies whose interfaces are not part of the IDispatch ... IAccessible2_3
hierarchy are not wrapped with handlers (though this might change in the future
if we need to expand coverage). AccessibleHandler implements IAccessible2_3 such
that, if we have cached data available for a particular IA2 method, we provide
that cached data to the client. Otherwise we pass on the request to the COM
proxy for retrieval via IPC.
The other class in the handler dll is AccessibleHandlerControl. This class
implements the IHandlerControl interface that is provided to IGeckoBackChannel.
Gecko dispatches cache invalidation events using this interface. This class
is a singleton within the handler dll and manages shared, handler-wide resources.
--HG--
extra : rebase_source : 4fc3910f789b0ed92c90655344ffb89f576ca5bd
2017-03-28 04:13:34 +03:00
|
|
|
IA2Payload mCachedData;
|
|
|
|
UniquePtr<mscom::StructToStream> mSerializer;
|
|
|
|
uint32_t mCacheGen;
|
2017-11-22 14:32:28 +03:00
|
|
|
IAccessibleHyperlink** mCachedHyperlinks;
|
|
|
|
long mCachedNHyperlinks;
|
|
|
|
IA2TextSegment* mCachedTextAttribRuns;
|
|
|
|
long mCachedNTextAttribRuns;
|
2018-02-02 02:38:51 +03:00
|
|
|
IARelationData* mCachedRelations;
|
|
|
|
long mCachedNRelations;
|
2020-03-03 18:48:22 +03:00
|
|
|
bool mIsEmulatedWindow;
|
Bug 1303060: Implementation of the caching COM handler for a11y; r=tbsaunde
MozReview-Commit-ID: HkiIgDQURtK
The a11y COM handler consists of two classes. AccessibleHandler is the one that
is actually interposed by COM between the client and the proxy. It implements
IAccessible2_3, IServiceProvider, and IProvideClassInfo. It is derived from
mscom::Handler which takes care of most of the COM boilerplate for handler
instantiation. AccessibleHandler must override a few virtual functions from
mscom::Handler:
* QueryHandlerInterface - mscom::Handler must implement the "real" QI. This is
the method that mscom::Handler uses to delegate to the implementer.
* ReadHandlerPayload - deserializing the payload. This uses
mscom::StructFromStream and the IA2Data_Decode function that was generated by
midl. It should essentially be the inverse of the serialization code in the
IHandlerProvider implementation inside Gecko.
* MarshalAs - identical to IHandlerProvider::MarshalAs
* GetHandlerPayloadSize and WriteHandlerPayload - it sucks that we have to
include these, but they are neccessary for the scenario when COM wants to
make a proxy of a proxy. When that happens, we need to get COM to serialize
the payload again; it isn't smart enough to recognize payloads in existing
proxies and copy them itself.
In order to reduce round trips, AccessibleHandler implements the most
sophisticated IA2 interface. This way the client has access to any of those
interfaces from IDispatch all the way down to IAccessible2_3 without needing to
incur additional round-trips to obtain them.
We also implement IServiceProvider so that a client may QueryService for an IA2
interface without needing to incur more round trips. In addition, we maintain
a list of service IDs that we definitely do not support, and handle those
locally instead of incurring an IPC round-trip.
We also implement IProvideClassInfo because NVDA's python code (and presumably
other ATs that use interpreted languages) supports using that interface to
assist its FFI library with resolution of our COM objects.
COM wraps each instance of an IAccessible* proxy with an AccessibleHandler
object. Proxies whose interfaces are not part of the IDispatch ... IAccessible2_3
hierarchy are not wrapped with handlers (though this might change in the future
if we need to expand coverage). AccessibleHandler implements IAccessible2_3 such
that, if we have cached data available for a particular IA2 method, we provide
that cached data to the client. Otherwise we pass on the request to the COM
proxy for retrieval via IPC.
The other class in the handler dll is AccessibleHandlerControl. This class
implements the IHandlerControl interface that is provided to IGeckoBackChannel.
Gecko dispatches cache invalidation events using this interface. This class
is a singleton within the handler dll and manages shared, handler-wide resources.
--HG--
extra : rebase_source : 4fc3910f789b0ed92c90655344ffb89f576ca5bd
2017-03-28 04:13:34 +03:00
|
|
|
};
|
|
|
|
|
2018-02-02 02:38:51 +03:00
|
|
|
inline static BSTR CopyBSTR(BSTR aSrc) {
|
2018-11-22 09:09:31 +03:00
|
|
|
if (!aSrc) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2018-02-02 02:38:51 +03:00
|
|
|
return ::SysAllocStringLen(aSrc, ::SysStringLen(aSrc));
|
|
|
|
}
|
|
|
|
|
Bug 1303060: Implementation of the caching COM handler for a11y; r=tbsaunde
MozReview-Commit-ID: HkiIgDQURtK
The a11y COM handler consists of two classes. AccessibleHandler is the one that
is actually interposed by COM between the client and the proxy. It implements
IAccessible2_3, IServiceProvider, and IProvideClassInfo. It is derived from
mscom::Handler which takes care of most of the COM boilerplate for handler
instantiation. AccessibleHandler must override a few virtual functions from
mscom::Handler:
* QueryHandlerInterface - mscom::Handler must implement the "real" QI. This is
the method that mscom::Handler uses to delegate to the implementer.
* ReadHandlerPayload - deserializing the payload. This uses
mscom::StructFromStream and the IA2Data_Decode function that was generated by
midl. It should essentially be the inverse of the serialization code in the
IHandlerProvider implementation inside Gecko.
* MarshalAs - identical to IHandlerProvider::MarshalAs
* GetHandlerPayloadSize and WriteHandlerPayload - it sucks that we have to
include these, but they are neccessary for the scenario when COM wants to
make a proxy of a proxy. When that happens, we need to get COM to serialize
the payload again; it isn't smart enough to recognize payloads in existing
proxies and copy them itself.
In order to reduce round trips, AccessibleHandler implements the most
sophisticated IA2 interface. This way the client has access to any of those
interfaces from IDispatch all the way down to IAccessible2_3 without needing to
incur additional round-trips to obtain them.
We also implement IServiceProvider so that a client may QueryService for an IA2
interface without needing to incur more round trips. In addition, we maintain
a list of service IDs that we definitely do not support, and handle those
locally instead of incurring an IPC round-trip.
We also implement IProvideClassInfo because NVDA's python code (and presumably
other ATs that use interpreted languages) supports using that interface to
assist its FFI library with resolution of our COM objects.
COM wraps each instance of an IAccessible* proxy with an AccessibleHandler
object. Proxies whose interfaces are not part of the IDispatch ... IAccessible2_3
hierarchy are not wrapped with handlers (though this might change in the future
if we need to expand coverage). AccessibleHandler implements IAccessible2_3 such
that, if we have cached data available for a particular IA2 method, we provide
that cached data to the client. Otherwise we pass on the request to the COM
proxy for retrieval via IPC.
The other class in the handler dll is AccessibleHandlerControl. This class
implements the IHandlerControl interface that is provided to IGeckoBackChannel.
Gecko dispatches cache invalidation events using this interface. This class
is a singleton within the handler dll and manages shared, handler-wide resources.
--HG--
extra : rebase_source : 4fc3910f789b0ed92c90655344ffb89f576ca5bd
2017-03-28 04:13:34 +03:00
|
|
|
} // namespace a11y
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
# endif // !defined(MOZILLA_INTERNAL_API)
|
|
|
|
|
Bug 1303060: Changes to a11y to enable the serving of a COM handler; r=tbsaunde
MozReview-Commit-ID: GTQF3x1pBtX
A general outline of the COM handler (a.k.a. the "smart proxy"):
COM handlers are pieces of code that are loaded by the COM runtime along with
a proxy and are layered above that proxy. This enables the COM handler to
interpose itself between the caller and the proxy, thus providing the
opportunity for the handler to manipulate an interface's method calls before
those calls reach the proxy.
Handlers are regular COM components that live in DLLs and are declared in the
Windows registry. In order to allow for the specifying of a handler (and an
optional payload to be sent with the proxy), the mscom library allows its
clients to specify an implementation of the IHandlerProvider interface.
IHandlerProvider consists of 5 functions:
* GetHandler returns the CLSID of the component that should be loaded into
the COM client's process. If GetHandler returns a failure code, then no
handler is loaded.
* GetHandlerPayloadSize and WriteHandlerPayload are for obtaining the payload
data. These calls are made on a background thread but need to do their work
on the main thread. We declare the payload struct in IDL. MIDL generates two
functions, IA2Payload_Encode and IA2Payload_Decode, which are used by
mscom::StructToStream to read and write that struct to and from buffers.
* The a11y payload struct also includes an interface, IGeckoBackChannel, that
allows the handler to communicate directly with Gecko. IGeckoBackChannel
currently provides two methods: one to allow the handler to request fresh
cache information, and the other to provide Gecko with its IHandlerControl
interface.
* MarshalAs accepts an IID that specifies the interface that is about to be
proxied. We may want to send a more sophisticated proxy than the one that
is requested. The desired IID is returned by this function. In the case of
a11y interfaces, we should always return IAccessible2_3 if we are asked for
one of its parent interfaces. This allows us to eliminate round trips to
resolve more sophisticated interfaces later on.
* NewInstance, which is needed to ensure that all descendent proxies are also
imbued with the same handler code.
The main focus of this patch is as follows:
1. Provide an implementation of the IHandlerProvider interface;
2. Populate the handler payload (ie, the cache) with data;
3. Modify CreateHolderFromAccessible to specify the HandlerPayload object;
4. Receive the IHandlerControl interface from the handler DLL and move it
into the chrome process.
Some more information about IHandlerControl:
There is one IHandlerControl per handler DLL instance. It is the interface that
we call in Gecko when we need to dispatch an event to the handler. In order to
ensure that events are dispatched in the correct order, we need to dispatch
those events from the chrome main thread so that they occur in sequential order
with calls to NotifyWinEvent.
--HG--
extra : rebase_source : acb44dead7cc5488424720e1bf58862b7b30374f
2017-04-05 00:23:55 +03:00
|
|
|
#endif // defined(__midl)
|
|
|
|
|
|
|
|
#endif // mozilla_a11y_AccessibleHandler_h
|