diff --git a/dom/base/nsWrapperCache.h b/dom/base/nsWrapperCache.h index 2fff9ac39fca..a9e31f56fc08 100644 --- a/dom/base/nsWrapperCache.h +++ b/dom/base/nsWrapperCache.h @@ -441,4 +441,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperCache, NS_WRAPPERCACHE_IID) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \ NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class) +// This is used for wrapper cached classes that inherit from cycle +// collected non-wrapper cached classes. +#define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_INHERITED(_class, _base, ...) \ + NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \ + NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(_class, _base) \ + NS_IMPL_CYCLE_COLLECTION_UNLINK(__VA_ARGS__) \ + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \ + NS_IMPL_CYCLE_COLLECTION_UNLINK_END \ + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(_class, _base) \ + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(__VA_ARGS__) \ + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \ + NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class) + #endif /* nsWrapperCache_h___ */ diff --git a/dom/u2f/U2F.cpp b/dom/u2f/U2F.cpp index 92fb53209c30..461f33e128a9 100644 --- a/dom/u2f/U2F.cpp +++ b/dom/u2f/U2F.cpp @@ -42,14 +42,13 @@ NS_NAMED_LITERAL_STRING( NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(U2F) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) - NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener) -NS_INTERFACE_MAP_END +NS_INTERFACE_MAP_END_INHERITING(WebAuthnManagerBase) -NS_IMPL_CYCLE_COLLECTING_ADDREF(U2F) -NS_IMPL_CYCLE_COLLECTING_RELEASE(U2F) +NS_IMPL_ADDREF_INHERITED(U2F, WebAuthnManagerBase) +NS_IMPL_RELEASE_INHERITED(U2F, WebAuthnManagerBase) -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(U2F, mParent) +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_INHERITED(U2F, WebAuthnManagerBase, + mTransaction) /*********************************************************************** * Utility Functions diff --git a/dom/u2f/U2F.h b/dom/u2f/U2F.h index e696358222d5..efafc08e1e1f 100644 --- a/dom/u2f/U2F.h +++ b/dom/u2f/U2F.h @@ -14,6 +14,7 @@ #include "mozilla/dom/U2FBinding.h" #include "mozilla/dom/WebAuthnManagerBase.h" #include "mozilla/ErrorResult.h" +#include "mozilla/Maybe.h" #include "mozilla/MozPromise.h" #include "nsProxyRelease.h" #include "nsWrapperCache.h" @@ -77,8 +78,9 @@ class U2FTransaction { class U2F final : public WebAuthnManagerBase, public nsWrapperCache { public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(U2F) + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(U2F, + WebAuthnManagerBase) explicit U2F(nsPIDOMWindowInner* aParent) : WebAuthnManagerBase(aParent) {} @@ -136,6 +138,26 @@ class U2F final : public WebAuthnManagerBase, public nsWrapperCache { Maybe mTransaction; }; +inline void ImplCycleCollectionTraverse( + nsCycleCollectionTraversalCallback& aCallback, U2FTransaction& aTransaction, + const char* aName, uint32_t aFlags = 0) { + if (aTransaction.HasRegisterCallback()) { + CycleCollectionNoteChild( + aCallback, aTransaction.GetRegisterCallback().get(), aName, aFlags); + } else { + CycleCollectionNoteChild(aCallback, aTransaction.GetSignCallback().get(), + aName, aFlags); + } +} + +inline void ImplCycleCollectionUnlink(U2FTransaction& aTransaction) { + if (aTransaction.HasRegisterCallback()) { + aTransaction.GetRegisterCallback() = nullptr; + } else { + aTransaction.GetSignCallback() = nullptr; + } +} + } // namespace dom } // namespace mozilla diff --git a/dom/webauthn/WebAuthnManager.cpp b/dom/webauthn/WebAuthnManager.cpp index 7800096e4325..c396c3618fe7 100644 --- a/dom/webauthn/WebAuthnManager.cpp +++ b/dom/webauthn/WebAuthnManager.cpp @@ -31,7 +31,11 @@ namespace { static mozilla::LazyLogModule gWebAuthnManagerLog("webauthnmanager"); } -NS_IMPL_ISUPPORTS(WebAuthnManager, nsIDOMEventListener); +NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(WebAuthnManager, + WebAuthnManagerBase) + +NS_IMPL_CYCLE_COLLECTION_INHERITED(WebAuthnManager, WebAuthnManagerBase, + mFollowingSignal, mTransaction) /*********************************************************************** * Utility Functions diff --git a/dom/webauthn/WebAuthnManager.h b/dom/webauthn/WebAuthnManager.h index 037ab77530e2..51361b2c14d0 100644 --- a/dom/webauthn/WebAuthnManager.h +++ b/dom/webauthn/WebAuthnManager.h @@ -7,6 +7,7 @@ #ifndef mozilla_dom_WebAuthnManager_h #define mozilla_dom_WebAuthnManager_h +#include "mozilla/Maybe.h" #include "mozilla/MozPromise.h" #include "mozilla/dom/PWebAuthnTransaction.h" #include "mozilla/dom/WebAuthnManagerBase.h" @@ -69,7 +70,8 @@ class WebAuthnTransaction { class WebAuthnManager final : public WebAuthnManagerBase, public AbortFollower { public: - NS_DECL_ISUPPORTS + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WebAuthnManager, WebAuthnManagerBase) explicit WebAuthnManager(nsPIDOMWindowInner* aParent) : WebAuthnManagerBase(aParent) {} @@ -117,6 +119,16 @@ class WebAuthnManager final : public WebAuthnManagerBase, public AbortFollower { Maybe mTransaction; }; +inline void ImplCycleCollectionTraverse( + nsCycleCollectionTraversalCallback& aCallback, + WebAuthnTransaction& aTransaction, const char* aName, uint32_t aFlags = 0) { + ImplCycleCollectionTraverse(aCallback, aTransaction.mPromise, aName, aFlags); +} + +inline void ImplCycleCollectionUnlink(WebAuthnTransaction& aTransaction) { + ImplCycleCollectionUnlink(aTransaction.mPromise); +} + } // namespace dom } // namespace mozilla diff --git a/dom/webauthn/WebAuthnManagerBase.cpp b/dom/webauthn/WebAuthnManagerBase.cpp index 779d863171cd..d9fd746f416d 100644 --- a/dom/webauthn/WebAuthnManagerBase.cpp +++ b/dom/webauthn/WebAuthnManagerBase.cpp @@ -24,6 +24,16 @@ WebAuthnManagerBase::WebAuthnManagerBase(nsPIDOMWindowInner* aParent) WebAuthnManagerBase::~WebAuthnManagerBase() { MOZ_ASSERT(NS_IsMainThread()); } +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebAuthnManagerBase) + NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTION(WebAuthnManagerBase, mParent) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(WebAuthnManagerBase) +NS_IMPL_CYCLE_COLLECTING_RELEASE(WebAuthnManagerBase) + /*********************************************************************** * IPC Protocol Implementation **********************************************************************/ diff --git a/dom/webauthn/WebAuthnManagerBase.h b/dom/webauthn/WebAuthnManagerBase.h index 65cf7c44d535..6eb228a453f9 100644 --- a/dom/webauthn/WebAuthnManagerBase.h +++ b/dom/webauthn/WebAuthnManagerBase.h @@ -25,6 +25,9 @@ class WebAuthnManagerBase : public nsIDOMEventListener { public: NS_DECL_NSIDOMEVENTLISTENER + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS(WebAuthnManagerBase) + explicit WebAuthnManagerBase(nsPIDOMWindowInner* aParent); virtual void FinishMakeCredential( @@ -41,7 +44,7 @@ class WebAuthnManagerBase : public nsIDOMEventListener { void ActorDestroyed(); protected: - ~WebAuthnManagerBase(); + virtual ~WebAuthnManagerBase(); // Needed by HandleEvent() to cancel transactions. virtual void CancelTransaction(const nsresult& aError) = 0; diff --git a/mfbt/Maybe.h b/mfbt/Maybe.h index 2a1a5e855e85..86b57c29e6b8 100644 --- a/mfbt/Maybe.h +++ b/mfbt/Maybe.h @@ -22,6 +22,13 @@ #include #include +class nsCycleCollectionTraversalCallback; + +template +inline void CycleCollectionNoteChild( + nsCycleCollectionTraversalCallback& aCallback, T* aChild, const char* aName, + uint32_t aFlags); + namespace mozilla { struct Nothing {}; @@ -619,6 +626,22 @@ bool operator>=(const Maybe& aLHS, const Maybe& aRHS) { return !(aLHS < aRHS); } +template +inline void ImplCycleCollectionTraverse( + nsCycleCollectionTraversalCallback& aCallback, mozilla::Maybe& aField, + const char* aName, uint32_t aFlags = 0) { + if (aField) { + ImplCycleCollectionTraverse(aCallback, aField.ref(), aName, aFlags); + } +} + +template +inline void ImplCycleCollectionUnlink(mozilla::Maybe& aField) { + if (aField) { + ImplCycleCollectionUnlink(aField.ref()); + } +} + } // namespace mozilla #endif /* mozilla_Maybe_h */ diff --git a/testing/web-platform/meta/webauthn/__dir__.ini b/testing/web-platform/meta/webauthn/__dir__.ini index ac090eb046f9..ee06be403fcf 100644 --- a/testing/web-platform/meta/webauthn/__dir__.ini +++ b/testing/web-platform/meta/webauthn/__dir__.ini @@ -1,2 +1 @@ prefs: [security.webauth.webauthn:true] -lsan-allowed: [Alloc, alloc_system::platform::_$LT$impl$u20$core..alloc..GlobalAlloc$u20$for$u20$alloc_system..System$GT$::alloc::, alloc_system::platform::_$LT$impl$u20$core..alloc..GlobalAlloc$u20$for$u20$alloc_system..System$GT$::realloc::, mozilla::dom::DOMException::Create, mozilla::dom::Navigator::Credentials, mozilla::dom::Performance::CreateForMainThread] diff --git a/xpcom/threads/nsProxyRelease.h b/xpcom/threads/nsProxyRelease.h index 1cb60af1169a..deb424590f3a 100644 --- a/xpcom/threads/nsProxyRelease.h +++ b/xpcom/threads/nsProxyRelease.h @@ -370,4 +370,21 @@ using PtrHandle = nsMainThreadPtrHandle; } // namespace mozilla +class nsCycleCollectionTraversalCallback; +template +void CycleCollectionNoteChild(nsCycleCollectionTraversalCallback& aCallback, + T* aChild, const char* aName, uint32_t aFlags); + +template +inline void ImplCycleCollectionTraverse( + nsCycleCollectionTraversalCallback& aCallback, + nsMainThreadPtrHandle& aField, const char* aName, uint32_t aFlags = 0) { + CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags); +} + +template +inline void ImplCycleCollectionUnlink(nsMainThreadPtrHandle& aField) { + aField = nullptr; +} + #endif