From abcf3a5a9d8b79c9663dc14e373cd97e678733a9 Mon Sep 17 00:00:00 2001 From: "rjc%netscape.com" Date: Wed, 13 Mar 2002 23:33:35 +0000 Subject: [PATCH] Fix bug # 129794 part deux: plug leak. r=shaver sr=ben a=asa --- xpfe/appshell/src/nsWindowMediator.cpp | 45 ++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/xpfe/appshell/src/nsWindowMediator.cpp b/xpfe/appshell/src/nsWindowMediator.cpp index dcd2c9ecc30..9c6279cde1c 100644 --- a/xpfe/appshell/src/nsWindowMediator.cpp +++ b/xpfe/appshell/src/nsWindowMediator.cpp @@ -182,7 +182,7 @@ nsIRDFResource *nsWindowMediator::kNC_Name = NULL; nsIRDFResource *nsWindowMediator::kNC_URL = NULL; nsIRDFResource *nsWindowMediator::kNC_KeyIndex = NULL; -PRInt32 nsWindowMediator::gRefCnt; +PRInt32 nsWindowMediator::gRefCnt = 0; nsIRDFContainer *nsWindowMediator::mContainer = NULL; nsIRDFDataSource *nsWindowMediator::mInner = NULL; @@ -842,11 +842,41 @@ nsWindowMediator::ConvertISupportsToDOMWindow( nsISupports* inInterface, // COM NS_IMPL_ADDREF( nsWindowMediator ); -NS_IMPL_RELEASE( nsWindowMediator ); NS_IMPL_QUERY_INTERFACE3(nsWindowMediator, nsIWindowMediator, nsIRDFDataSource, nsIRDFObserver); +NS_IMETHODIMP_(nsrefcnt) +nsWindowMediator::Release() +{ + // We need a special implementation of Release() due to having + // two circular references: mInner and mContainer + + NS_PRECONDITION(PRInt32(mRefCnt) > 0, "duplicate release"); + --mRefCnt; + NS_LOG_RELEASE(this, mRefCnt, "nsWindowMediator"); + + if (mInner && mRefCnt == 2) + { + NS_IF_RELEASE(mContainer); + mContainer = nsnull; + + nsIRDFDataSource* tmp = mInner; + mInner = nsnull; + NS_IF_RELEASE(tmp); + return(0); + } + else if (mRefCnt == 0) + { + mRefCnt = 1; + delete this; + return(0); + } + return(mRefCnt); +} + + + // RDF nsresult nsWindowMediator::Init() @@ -874,6 +904,8 @@ nsWindowMediator::Init() if (NS_FAILED(rv)) return rv; + // note: by using "this" as an observer, mInner becomes a circular reference + // back to us, requiring a special ::Release() rv = mInner->AddObserver(this); if (NS_FAILED(rv)) return rv; @@ -882,7 +914,9 @@ nsWindowMediator::Init() if (NS_FAILED(rv)) return rv; - // note: use "this" instead of "mInner" so that we can use batching + // note: use "this" instead of "mInner" so that we can use batching... + // by doing so, mContainer becomes a circular reference back to us, + // requiring a special ::Release() rv = rdfc->MakeSeq(this, kNC_WindowMediatorRoot, &mContainer ); NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to make NC:WindowMediatorRoot a sequence"); if (NS_FAILED(rv)) @@ -938,6 +972,11 @@ nsWindowMediator::GetTarget(nsIRDFResource* source, PRBool tv, nsIRDFNode** target) { + NS_PRECONDITION(target != nsnull, "null ptr"); + if (! target) + return(NS_ERROR_NULL_POINTER); + *target = nsnull; + if (property == kNC_KeyIndex) { PRInt32 theIndex = 0;