Bug 1694865 part 5: Move shutdown code into MsaaAccessible. r=morgan

Differential Revision: https://phabricator.services.mozilla.com/D112936
This commit is contained in:
James Teh 2021-04-28 06:21:45 +00:00
Родитель 6e9e04fb17
Коммит 7aa8ea0a24
4 изменённых файлов: 54 добавлений и 48 удалений

Просмотреть файл

@ -44,7 +44,6 @@
#include "mozilla/Preferences.h"
#include "mozilla/ReverseIterator.h"
#include "mozilla/mscom/AsyncInvoker.h"
#include "mozilla/mscom/Interceptor.h"
#include "oleacc.h"
@ -81,37 +80,7 @@ ITypeInfo* AccessibleWrap::gTypeInfo = nullptr;
NS_IMPL_ISUPPORTS_INHERITED0(AccessibleWrap, LocalAccessible)
void AccessibleWrap::Shutdown() {
if (mID != kNoID) {
auto doc = static_cast<DocAccessibleWrap*>(mDoc.get());
// Accessibles can be shut down twice in some cases. When this happens,
// doc will be null.
if (doc) {
doc->RemoveID(mID);
}
}
if (XRE_IsContentProcess()) {
// Bug 1434822: To improve performance for cross-process COM, we disable COM
// garbage collection. However, this means we never receive Release calls
// from clients, so defunct accessibles can never be deleted. Since we
// know when an accessible is shutting down, we can work around this by
// forcing COM to disconnect this object from all of its remote clients,
// which will cause associated references to be released.
IUnknown* unk = static_cast<IAccessible*>(this);
mscom::Interceptor::DisconnectRemotesForTarget(unk);
// If an accessible was retrieved via IAccessibleHypertext::hyperlink*,
// it will have a different Interceptor that won't be matched by the above
// call, even though it's the same object. Therefore, call it again with
// the IAccessibleHyperlink pointer. We can remove this horrible hack once
// bug 1440267 is fixed.
unk = static_cast<IAccessibleHyperlink*>(this);
mscom::Interceptor::DisconnectRemotesForTarget(unk);
for (auto& assocUnk : mAssociatedCOMObjectsForDisconnection) {
mscom::Interceptor::DisconnectRemotesForTarget(assocUnk);
}
mAssociatedCOMObjectsForDisconnection.Clear();
}
MsaaShutdown();
LocalAccessible::Shutdown();
}

Просмотреть файл

@ -167,20 +167,6 @@ class AccessibleWrap : public LocalAccessible, public MsaaAccessible {
static void UpdateSystemCaretFor(RemoteAccessible* aProxy,
const LayoutDeviceIntRect& aCaretRect);
/**
* Associate a COM object with this LocalAccessible so it will be disconnected
* from remote clients when this LocalAccessible shuts down.
* This should only be called with separate COM objects with a different
* IUnknown to this AccessibleWrap; e.g. IAccessibleRelation.
*/
void AssociateCOMObjectForDisconnection(IUnknown* aObject) {
// We only need to track these for content processes because COM garbage
// collection is disabled there.
if (XRE_IsContentProcess()) {
mAssociatedCOMObjectsForDisconnection.AppendElement(aObject);
}
}
private:
static void UpdateSystemCaretFor(HWND aCaretWnd,
const LayoutDeviceIntRect& aCaretRect);
@ -268,8 +254,6 @@ class AccessibleWrap : public LocalAccessible, public MsaaAccessible {
};
static StaticAutoPtr<nsTArray<HandlerControllerData>> sHandlerControllers;
nsTArray<RefPtr<IUnknown>> mAssociatedCOMObjectsForDisconnection;
};
static inline AccessibleWrap* WrapperFor(const RemoteAccessible* aProxy) {

Просмотреть файл

@ -7,6 +7,7 @@
#include "MsaaAccessible.h"
#include "mozilla/dom/BrowserBridgeParent.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/mscom/Interceptor.h"
#include "sdnAccessible.h"
using namespace mozilla;
@ -22,6 +23,39 @@ MsaaAccessible::~MsaaAccessible() {
}
}
void MsaaAccessible::MsaaShutdown() {
if (mID != kNoID) {
auto doc = static_cast<DocAccessibleWrap*>(LocalAcc()->Document());
// Accessibles can be shut down twice in some cases. When this happens,
// doc will be null.
if (doc) {
doc->RemoveID(mID);
}
}
if (XRE_IsContentProcess()) {
// Bug 1434822: To improve performance for cross-process COM, we disable COM
// garbage collection. However, this means we never receive Release calls
// from clients, so defunct accessibles can never be deleted. Since we
// know when an accessible is shutting down, we can work around this by
// forcing COM to disconnect this object from all of its remote clients,
// which will cause associated references to be released.
IUnknown* unk = static_cast<IAccessible*>(this);
mscom::Interceptor::DisconnectRemotesForTarget(unk);
// If an accessible was retrieved via IAccessibleHypertext::hyperlink*,
// it will have a different Interceptor that won't be matched by the above
// call, even though it's the same object. Therefore, call it again with
// the IAccessibleHyperlink pointer. We can remove this horrible hack once
// bug 1440267 is fixed.
unk = static_cast<IAccessibleHyperlink*>(this);
mscom::Interceptor::DisconnectRemotesForTarget(unk);
for (auto& assocUnk : mAssociatedCOMObjectsForDisconnection) {
mscom::Interceptor::DisconnectRemotesForTarget(assocUnk);
}
mAssociatedCOMObjectsForDisconnection.Clear();
}
}
void MsaaAccessible::SetID(uint32_t aID) {
MOZ_ASSERT(XRE_IsParentProcess() &&
static_cast<AccessibleWrap*>(this)->IsProxy());

Просмотреть файл

@ -13,6 +13,7 @@
#include "ia2AccessibleValue.h"
#include "mozilla/a11y/MsaaIdGenerator.h"
#include "mozilla/dom/ipc/IdType.h"
#include "nsXULAppAPI.h"
namespace mozilla {
namespace a11y {
@ -45,6 +46,22 @@ class MsaaAccessible : public ia2Accessible,
[[nodiscard]] already_AddRefed<IAccessible> GetIAccessibleFor(
const VARIANT& aVarChild, bool* aIsDefunct);
/**
* Associate a COM object with this MsaaAccessible so it will be disconnected
* from remote clients when this MsaaAccessible shuts down.
* This should only be called with separate COM objects with a different
* IUnknown to this MsaaAccessible; e.g. IAccessibleRelation.
*/
void AssociateCOMObjectForDisconnection(IUnknown* aObject) {
// We only need to track these for content processes because COM garbage
// collection is disabled there.
if (XRE_IsContentProcess()) {
mAssociatedCOMObjectsForDisconnection.AppendElement(aObject);
}
}
void MsaaShutdown();
protected:
virtual ~MsaaAccessible();
@ -60,6 +77,8 @@ class MsaaAccessible : public ia2Accessible,
*/
[[nodiscard]] already_AddRefed<IAccessible> GetRemoteIAccessibleFor(
const VARIANT& aVarChild);
nsTArray<RefPtr<IUnknown>> mAssociatedCOMObjectsForDisconnection;
};
} // namespace a11y