1. CleanupStaticIA2Data just called ReleaseStaticIA2DataInterfaces and zeroed memory.
We don't need it to zero memory, since we're going to delete the data anyway.
So, just call ReleaseStaticIA2DataInterfaces directly and get rid of CleanupStaticIA2Data.
2. CleanupDynamicIA2Data had a aZeroMemory argument, but no caller ever set it to true.
Therefore, get rid of the argument.
Differential Revision: https://phabricator.services.mozilla.com/D70297
When window emulation is enabled, each tab document gets its own HWND.
OOP iframes get the same HWND as their tab document and fire events with that HWND.
However, the root accessible for the HWND (the tab document) can't return accessibles for OOP iframes.
Therefore, we must get the root accessible from the main HWND and call accChild on that instead.
We must do this in the parent process, but the tab document accessible is in the content process.
Although OOP a11y clients talk directly to the content process, the clients that need window emulation are in-process.
All in-process client calls get intercepted by AccessibleHandler, so we can deal with this forwarding in AccessibleHandler.
Differential Revision: https://phabricator.services.mozilla.com/D65054
--HG--
extra : moz-landing-system : lando
The inclusions were removed with the following very crude script and the
resulting breakage was fixed up by hand. The manual fixups did either
revert the changes done by the script, replace a generic header with a more
specific one or replace a header with a forward declaration.
find . -name "*.idl" | grep -v web-platform | grep -v third_party | while read path; do
interfaces=$(grep "^\(class\|interface\).*:.*" "$path" | cut -d' ' -f2)
if [ -n "$interfaces" ]; then
if [[ "$interfaces" == *$'\n'* ]]; then
regexp="\("
for i in $interfaces; do regexp="$regexp$i\|"; done
regexp="${regexp%%\\\|}\)"
else
regexp="$interfaces"
fi
interface=$(basename "$path")
rg -l "#include.*${interface%%.idl}.h" . | while read path2; do
hits=$(grep -v "#include.*${interface%%.idl}.h" "$path2" | grep -c "$regexp" )
if [ $hits -eq 0 ]; then
echo "Removing ${interface} from ${path2}"
grep -v "#include.*${interface%%.idl}.h" "$path2" > "$path2".tmp
mv -f "$path2".tmp "$path2"
fi
done
fi
done
Differential Revision: https://phabricator.services.mozilla.com/D55443
--HG--
extra : moz-landing-system : lando
When a client wants to fetch all accessible children, the COM handler uses handlerProvider::get_AllChildren in the content process to optimize cross-process retrieval of all children.
This works fine for iframes rendered in the same content process, just as it does for other accessibles.
However, for out-of-process iframes, HandlerProvider::get_AllChildren will fail.
This is because we only send down an IDispatch COM proxy for the embedded document, but get_AllChildren will try to QueryInterface this to IAccessible2 to reduce QI calls from the parent process.
Because the content process is sandboxed, it can't make the outgoing COM call to QI the proxy from IDispatch to IAccessible2 and so it fails.
Since an iframe only has one child anyway, we don't need the bulk fetch optimization offered by HandlerChildEnumerator or even IEnumVARIANT.
Therefore, we explicitly tell the client this interface is not supported, which will cause the oleacc AccessibleChildren function to fall back to accChild.
Differential Revision: https://phabricator.services.mozilla.com/D34494
--HG--
extra : moz-landing-system : lando
On mingw this causes IIDs to be defined in headers. Those definitions conflict with _i.c files that are included as well. Since we include _i.c anyway, INITGUID is simply not needed.
The singleton AccessibleHandlerControl maintains a global cache generation counter which is incremented whenever any node is changed.
The handler for each node tracks the cache generation at the time its cache was initialized.
To check whether the cache needs to be updated, the handler compares its generation against the global generation from AccessibleHandlerControl.
If they differ, it refreshes the cache.
Previously, the handler didn't update its cache generation after refreshing.
This meant that every single query after the first change would refresh the whole cache, even if there wasn't a second change.
This resulted in a huge number of wasted cache updates for clients such as JAWS which hold onto accessibles, rather than releasing them and fetching them again for each update.
MozReview-Commit-ID: 80d4n1cIjzQ
--HG--
extra : rebase_source : a0903ddb33eba5381a232a661deaa3754b92406f
A typo meant we were checking the address of mChildCount, not the value.
MozReview-Commit-ID: 7Hit3FBy9pr
--HG--
extra : amend_source : edb85b8e73184e47cd9ff42c0442f89d5f3c5152
Now that the handler implements IEnumVARIANT itself (and uses our own internal method to retrieve the children), caching this remote interface is pointless.
MozReview-Commit-ID: FyagiEcHMP2
--HG--
extra : rebase_source : 267568164fb46d98c8cde22dfbb4f36f2afceb8c
This implements IEnumVARIANT locally using the new method provided by HandlerProvider.
This avoids marshaling full objects for text leaf accessibles (instead using HandlerTextLeaf), which is much faster.
It also avoids a pointless cross-process call to IEnumVARIANT::Reset (and possibly IEnumVARIANT::Clone).
Finally, it caches children after the first query so that clients (such as UI Automation) which walk children one by one don't incur separate cross-process calls for every child.
MozReview-Commit-ID: KUIXQoXxInQ
--HG--
extra : rebase_source : a6c0a56c2bb65e227f7c45eb1b767e7df19efa49
If a client calls IAccessible2::nRelations, it's likely that it will next call IAccessible2::relations to query each relation.
Furthermore, it's likely the client will call relationType and nTargets on each relation.
Therefore, fetch all of this info when nRelations is called.
The number of relations is immediately returned to the client.
The rest of the info is cached and returned to the client when the appropriate methods are called.
The info is only cached for one call; i.e. after the client calls relations once, the cache is dropped.
This makes memory management simpler and lowers the risk of cache invalidation problems.
MozReview-Commit-ID: IBoJbu42osG
--HG--
extra : rebase_source : d1af83f4c6c0e7762299e9e3da95a67217157200
JAWS uses QueryService for these.
Using QI avoids a cross-process call, since we have these interfaces cached.
More importantly, if QS is used, the handler won't get used for that object, so our caching won't be used.
MozReview-Commit-ID: Ejc2Bjp7NSv
--HG--
extra : rebase_source : f0154a6691d4d6be97e9aa60b0613ff04f76b7ff
We just return failure for these, thus avoiding a pointless cross-process call.
I also updated the comment for an existing service, since I discovered its constant name.
MozReview-Commit-ID: E5hjhR6nYtv
--HG--
extra : rebase_source : 8f01da6b98a881809a106a03eb611aadc90a6d20
Previously, it was querying for IID_IAccessibleHypertext, but this is actually an IAccessibleHypertext2 pointer.
This meant we were crashing when trying to call an IAccessibleHypertext2 method.
This was a regression introduced in bug 1419362.
MozReview-Commit-ID: 7akjIfNuIh3
--HG--
extra : rebase_source : 18e126e3b47bc5a8f486870a285668a7f85e95c9
Both Provider and Handler need to release the interfaces in StaticIA2Data.
Therefore, move this into a common function to avoid duplication pain in future.
MozReview-Commit-ID: 7J4iuvDa8m2
--HG--
extra : rebase_source : 98c97b51c27c318ba987787518cfd70bda8967d4
We need to clean up the VARIANT and BSTRs in DynamicIA2Data in the handler as well.
We do this in two places:
1. Before reading a new payload (because we need to clean up the existing payload); and
2. When we're being destroyed.
MozReview-Commit-ID: GvO7csuxtwZ
--HG--
extra : rebase_source : 92cc9a64deddee07bbbc77e53117c15351816778
If a client requests all text (via IAccessibleText::text with IA2_TEXT_OFFSET_LENGTH), it's quite likely they will want all other information about the text as well; i.e. embedded objects and attributes.
Therefore, fetch all of this using a single cross-process call.
The text is immediately returned to the client.
The hyperlinks and attributes are cached for later return to the client when they call the appropriate methods.
They are only cached for one call; i.e. after the client retrieves them, the cache is dropped.
This makes memory management simpler and lowers the risk of cache invalidation problems.
MozReview-Commit-ID: FgFkX8J7wg1
--HG--
extra : rebase_source : e521d6ca7b00fcf1aad1f0ada299bac4c4b85c50
We want to be able to cache data related to both IAccessibleText and IAccessibleHypertext2 in a single call.
This is difficult with the tearoff because separate instances of the tearoff get created for the two interfaces.
Ensuring we use the same instance means working around reference cycles.
We could maintain a separate cache object, but that makes things more complex.
Therefore, it's much simpler to get rid of the tearoff.
A few things to note:
1. ResolveAccHypertext has been renamed to ResolveIAHypertext for consistency with the rest of AccessibleHandler.
2. mAccHypertextProxy has been renamed to mIAHypertextPassThru for consistency with the rest of AccessibleHandler.
3. mIAHypertextPassThru is a weak reference (just like the rest of the passthru pointers) because it refers to a proxy interface and the proxy aggregates the handler.
Thus, we release it immediately to avoid reference cycles.
When it was a tearoff, this was not the case; it was a strong reference.
MozReview-Commit-ID: 8NwPA0T1MFX
--HG--
extra : rebase_source : 57c4d19516d01b820bb3b4c1a9974ff3b889ed64
1. Bug 1363595 added support for retrieving accDefaultAction from the cache, but the value was never cached in the first place.
This would have meant that accDefaultAction was returning nothing to clients.
2. Since accDefaultAction is the name of the first action, we can also use this cached value for IAccessibleAction::name for index 0.
MozReview-Commit-ID: 6PGRH45kKdB
--HG--
extra : rebase_source : 52688f1e44ad7613c5dd14903b6240a51aa2d4eb
The handler's implementation of IAHyperlink just forwards calls through to the proxy.
However, it exists because we want the cache to be used when a hyperlink is retrieved.
When querying from the handler to IAHyperlink, we should use the same implementation.
This is mostly about consistency/correctness, especially as we're increasing complexity.
MozReview-Commit-ID: AwYibrFzUyf
--HG--
extra : rebase_source : 3d8f33639190a4220a21d0a6eeac401829d8345c
The proxy manager caches interfaces marshaled in the payload and returns them on QI without a cross-process call.
However, it doesn't know about interfaces which don't exist.
We can determine this from the payload, since interfaces which don't exist will have a null pointer.
We use this information to avoid querying the proxy in this case.
MozReview-Commit-ID: FnzDetmTiPP
--HG--
extra : rebase_source : 076ce714a69d3883a149487e5f9235ff495eedd0
Now that virtual buffers have to render across processes, we want to eliminate as many cross-process calls as possible.
This includes QueryInterface calls, since buffers query for several interfaces on every node they visit.
To avoid these cross-process QI calls, we include interfaces clients are likely to request in the handler payload.
This way, they get marshaled in the single call used to retrieve the object.
This patch does the following:
1. Passes the interceptor when building the payload.
We need this so we can get interceptors for other interfaces.
2. Splits the payload into two main parts: a static part and a dynamic part.
The (new) static part contains the interface pointers. The dynamic part contains the rest.
This is necessary because the refresh call cannot pass the interceptor, but the interceptor is needed to build the static part.
Also, re-building the static part is pointless when refreshing.
3. Includes the interface pointers in the payload (BuildStaticIA2Data).
The pointers also have to be cleaned up after marshaling.
4. Releases the interface pointers in the handler after the payload is received.
We do this because they're aggregated by the proxy manager as they're unmarshaled.
MozReview-Commit-ID: 6VRLMNScgwW
--HG--
extra : rebase_source : 249589643b7a69e870962ea55a44849bf03a2693
Bug 873444 implemented support for IAccessibleHypertext2.
AccessibleHandler's AccessibleTextTearoff needs to be updated accordingly, thus eliminating an additional cross-process QueryInterface for IAHypertext2 when the client also wants IAText.
MozReview-Commit-ID: EGqYX7jY9Cp
--HG--
extra : rebase_source : cc79b605bf75538bebc10b104e5f6771bc52d2f4
IAccessibleHypertext::hyperlink returns an IAccessibleHyperlink, not an IAccessible2.
previously, the handler didn't know about this interface, so it wasn't used.
Thus, any accessibles retrieved in this way did not benefit from the cache.
This patch teaches the handler about IAccessibleHyperlink so the handler gets used in this case.
MozReview-Commit-ID: 17CxxGyCLrE
--HG--
extra : rebase_source : 7f933bfd880c9ee009eafe8cee4ece4ef83004cd
IAccessible2_2::get_attribute is not implemented yet in Gecko.
However, the handler still passes this through, thus resulting in a pointless cross-process call.
Instead, just return E_NOTIMPL in the handler for this method.
MozReview-Commit-ID: 5XHieUC4cuz
--HG--
extra : rebase_source : 814ceda6d9dd4ec26f05a4ff90bbd4af2a6eb84e
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