Bug 1875528 - Part 6: Allow cycle-collecting the strong IPDL Manager reference, r=mccr8

There are a few IPDL actors which are cycle-collected, including `PBrowser`,
`PContent`, and `PWindowGlobal`.

This patch adds support for these actors to traverse and unlink the new strong
Manager() reference added by IPDL, allowing cycles containing these actors to
be properly unlinked and avoiding leaks.

Differential Revision: https://phabricator.services.mozilla.com/D198629
This commit is contained in:
Nika Layzell 2024-04-22 17:13:24 +00:00
parent de742b93d4
commit 33e1dcc9e0
5 changed files with 62 additions and 6 deletions

View file

@ -265,7 +265,22 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BrowserParent)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEventListener)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_WEAK(BrowserParent, mFrameLoader, mBrowsingContext)
NS_IMPL_CYCLE_COLLECTION_CLASS(BrowserParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowserParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameLoader)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext)
tmp->UnlinkManager();
NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowserParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameLoader)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(Manager())
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(BrowserParent)
NS_IMPL_CYCLE_COLLECTING_RELEASE(BrowserParent)

View file

@ -867,9 +867,26 @@ nsISupports* WindowGlobalChild::GetParentObject() {
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_WEAK_PTR(WindowGlobalChild, mWindowGlobal,
mContainerFeaturePolicy,
mWindowContext)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(WindowGlobalChild)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WindowGlobalChild)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindowGlobal)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mContainerFeaturePolicy)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindowContext)
tmp->UnlinkManager();
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_PTR
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WindowGlobalChild)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindowGlobal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContainerFeaturePolicy)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindowContext)
if (!tmp->IsInProcess()) {
CycleCollectionNoteChild(cb, static_cast<BrowserChild*>(tmp->Manager()),
"Manager()");
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WindowGlobalChild)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY

View file

@ -1713,8 +1713,22 @@ IPCResult WindowGlobalParent::RecvOnInitialStorageAccess() {
return IPC_OK();
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(WindowGlobalParent, WindowContext,
mPageUseCountersWindow)
NS_IMPL_CYCLE_COLLECTION_CLASS(WindowGlobalParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WindowGlobalParent,
WindowContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPageUseCountersWindow)
tmp->UnlinkManager();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WindowGlobalParent,
WindowContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPageUseCountersWindow)
if (!tmp->IsInProcess()) {
CycleCollectionNoteChild(cb, static_cast<BrowserParent*>(tmp->Manager()),
"Manager()");
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(WindowGlobalParent,
WindowContext)

View file

@ -504,6 +504,11 @@ void IProtocol::SetManagerAndRegister(IRefCountedProtocol* aManager,
aManager->RegisterID(this, aId);
}
void IProtocol::UnlinkManager() {
mToplevel = nullptr;
mManager = nullptr;
}
bool IProtocol::ChannelSend(UniquePtr<IPC::Message> aMsg) {
if (CanSend()) {
// NOTE: This send call failing can only occur during toplevel channel

View file

@ -241,6 +241,11 @@ class IProtocol : public HasResultCodes {
// calls SetManager.
void SetManager(IRefCountedProtocol* aManager);
// Clear `mManager` and `mToplevel` to nullptr. Only intended to be called
// within the unlink implementation of cycle collected IPDL actors with cycle
// collected managers.
void UnlinkManager();
// Sets the manager for the protocol and registers the protocol with
// its manager, setting up channels for the protocol as well. Not
// for use outside of IPDL.