Fix for bug 372713 (Add cycle collection to RDF datasources). r=bsmedberg, sr=dbaron.
authorpeterv@propagandism.org
Tue, 10 Apr 2007 15:05:41 -0700
changeset 456 0ad8bf431cbcfb5cc2c306e4ad9c47bad964828b
parent 455 16eab4febf5c3a4a46e3ce650197ca0348423bb0
child 457 cf4a4cdd5a6e2c2d334c85348ab6028ce7aa241c
push idunknown
push userunknown
push dateunknown
reviewersbsmedberg, dbaron
bugs372713
milestone1.9a4pre
Fix for bug 372713 (Add cycle collection to RDF datasources). r=bsmedberg, sr=dbaron.
browser/components/bookmarks/src/nsBookmarksService.cpp
browser/components/bookmarks/src/nsBookmarksService.h
browser/components/bookmarks/src/nsForwardProxyDataSource.cpp
browser/components/bookmarks/src/nsForwardProxyDataSource.h
content/xul/templates/src/nsXULTemplateBuilder.cpp
content/xul/templates/src/nsXULTemplateQueryProcessorRDF.cpp
rdf/base/src/nsCompositeDataSource.cpp
rdf/base/src/nsInMemoryDataSource.cpp
rdf/base/src/nsRDFXMLDataSource.cpp
rdf/chrome/src/nsChromeUIDataSource.cpp
rdf/chrome/src/nsChromeUIDataSource.h
rdf/datasource/src/nsFileSystemDataSource.cpp
rdf/datasource/src/nsFileSystemDataSource.h
rdf/datasource/src/nsLocalStore.cpp
toolkit/components/downloads/src/nsDownloadManager.cpp
toolkit/components/downloads/src/nsDownloadManager.h
toolkit/components/history/src/nsGlobalHistory.cpp
toolkit/components/history/src/nsGlobalHistory.h
xpcom/base/nsAgg.h
xpfe/components/intl/nsCharsetMenu.cpp
xpfe/components/related/src/nsRelatedLinksHandler.cpp
xpfe/components/related/src/nsRelatedLinksHandlerImpl.h
xpfe/components/search/src/nsLocalSearchService.cpp
xpfe/components/search/src/nsLocalSearchService.h
xpfe/components/windowds/nsWindowDataSource.cpp
xpfe/components/windowds/nsWindowDataSource.h
--- a/browser/components/bookmarks/src/nsBookmarksService.cpp
+++ b/browser/components/bookmarks/src/nsBookmarksService.cpp
@@ -1657,17 +1657,16 @@ BookmarkParser::AssertTime(nsIRDFResourc
     }
     return rv;
 }
 
 ////////////////////////////////////////////////////////////////////////
 // nsBookmarksService implementation
 
 nsBookmarksService::nsBookmarksService() :
-    mInner(nsnull),
     mUpdateBatchNest(0),
     mBookmarksAvailable(PR_FALSE),
     mDirty(PR_FALSE),
     mNeedBackupUpdate(PR_FALSE)
 { }
 
 nsBookmarksService::~nsBookmarksService()
 {
@@ -1682,17 +1681,16 @@ nsBookmarksService::~nsBookmarksService(
     // Unregister ourselves from the RDF service
     if (gRDF)
         gRDF->UnregisterDataSource(this);
 
     // Note: can't flush in the DTOR, as the RDF service
     // has probably already been destroyed
     // Flush();
     bm_ReleaseGlobals();
-    NS_IF_RELEASE(mInner);
 }
 
 nsresult
 nsBookmarksService::Init()
 {
     nsresult rv;
     rv = bm_AddRefGlobals();
     if (NS_FAILED(rv))  return rv;
@@ -2514,52 +2512,43 @@ NS_IMETHODIMP nsBookmarksService::Observ
 
     return rv;
 }
 
 
 ////////////////////////////////////////////////////////////////////////
 // nsISupports methods
 
-NS_IMPL_ADDREF(nsBookmarksService)
-
-NS_IMETHODIMP_(nsrefcnt)
-nsBookmarksService::Release()
-{
-    // We need a special implementation of Release() because our mInner
-    // holds a Circular References back to us.
-    NS_PRECONDITION(PRInt32(mRefCnt) > 0, "duplicate release");
-    --mRefCnt;
-    NS_LOG_RELEASE(this, mRefCnt, "nsBookmarksService");
-
-    if (mInner && mRefCnt == 1) {
-        nsIRDFDataSource* tmp = mInner;
-        mInner = nsnull;
-        NS_IF_RELEASE(tmp);
-        return 0;
-    }
-    else if (mRefCnt == 0) {
-        delete this;
-        return 0;
-    }
-    else {
-        return mRefCnt;
-    }
-}
-
-NS_IMPL_QUERY_INTERFACE9(nsBookmarksService,
-             nsIBookmarksService,
-             nsIRDFDataSource,
-             nsIRDFRemoteDataSource,
-             nsIRDFObserver,
-             nsIStreamListener,
-             nsIRequestObserver,
-             nsICharsetResolver,
-             nsIObserver,
-             nsISupportsWeakReference)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsBookmarksService)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsBookmarksService)
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mObservers)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsBookmarksService)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInner)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mObservers)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsBookmarksService,
+                                          nsIBookmarksService)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsBookmarksService,
+                                           nsIBookmarksService)
+
+NS_INTERFACE_MAP_BEGIN(nsBookmarksService)
+    NS_INTERFACE_MAP_ENTRY(nsIBookmarksService)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFRemoteDataSource)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFObserver)
+    NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
+    NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
+    NS_INTERFACE_MAP_ENTRY(nsICharsetResolver)
+    NS_INTERFACE_MAP_ENTRY(nsIObserver)
+    NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBookmarksService)
+    NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsBookmarksService)
+NS_INTERFACE_MAP_END
 
 
 ////////////////////////////////////////////////////////////////////////
 // nsIBookmarksService
 
 nsresult
 nsBookmarksService::InsertResource(nsIRDFResource* aResource,
                                    nsIRDFResource* aParentFolder, PRInt32 aIndex)
@@ -4590,20 +4579,19 @@ nsBookmarksService::ReadBookmarks(PRBool
     return NS_OK;
 }
 
 nsresult
 nsBookmarksService::InitDataSource()
 {
     // the profile manager might call Readbookmarks() in certain circumstances
     // so we need to forget about any previous bookmarks
-    NS_IF_RELEASE(mInner);
-
     // don't change this to an xml-ds, it will cause serious perf problems
-    nsresult rv = CallCreateInstance(kRDFInMemoryDataSourceCID, &mInner);
+    nsresult rv;
+    mInner = do_CreateInstance(kRDFInMemoryDataSourceCID, &rv);
     if (NS_FAILED(rv)) return rv;
 
     rv = mInner->AddObserver(this);
     if (NS_FAILED(rv)) return rv;
 
     rv = gRDFC->MakeSeq(mInner, kNC_BookmarksTopRoot, nsnull);
     NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to make NC:BookmarksTopRoot a sequence");
     if (NS_FAILED(rv)) return rv;
--- a/browser/components/bookmarks/src/nsBookmarksService.h
+++ b/browser/components/bookmarks/src/nsBookmarksService.h
@@ -53,16 +53,17 @@
 #include "nsIObserver.h"
 #include "nsWeakReference.h"
 #include "nsCOMArray.h"
 #include "nsIIOService.h"
 #include "nsICacheService.h"
 #include "nsICacheSession.h"
 #include "nsIPrefBranch.h"
 #include "nsICharsetResolver.h"
+#include "nsCycleCollectionParticipant.h"
 
 class nsIOutputStream;
 
 #ifdef DEBUG
 #ifdef XP_MACOSX
 #include <Timer.h>
 #endif
 #endif
@@ -72,17 +73,17 @@ class nsBookmarksService : public nsIBoo
                            public nsIRDFRemoteDataSource,
                            public nsIStreamListener,
                            public nsICharsetResolver,
                            public nsIRDFObserver,
                            public nsIObserver,
                            public nsSupportsWeakReference
 {
 protected:
-    nsIRDFDataSource*               mInner;
+    nsCOMPtr<nsIRDFDataSource>      mInner;
     nsCOMPtr<nsIRDFResource>        busyResource;
     nsCOMArray<nsIRDFObserver>      mObservers;
     nsCOMPtr<nsIStringBundle>       mBundle;
     nsCOMPtr<nsITimer>              mTimer;
     nsCOMPtr<nsIIOService>          mNetService;
     nsCOMPtr<nsICacheService>       mCacheService;
     nsCOMPtr<nsICacheSession>       mCacheSession;
 
@@ -192,17 +193,19 @@ public:
     virtual ~nsBookmarksService();
     nsresult Init();
 
     // we really need to figure out our public/private interface story
     void RemoveBookmark(nsIRDFResource* aBookmark);
     nsresult ClearBookmarksContainer(nsIRDFResource* aContainer);
 
     // nsISupports
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsBookmarksService,
+                                             nsIBookmarksService)
 
     // nsIBookmarksService
     NS_DECL_NSIBOOKMARKSSERVICE
 
     // nsIRDFDataSource
     NS_IMETHOD GetURI(char* *uri);
 
     NS_IMETHOD GetSource(nsIRDFResource* property,
--- a/browser/components/bookmarks/src/nsForwardProxyDataSource.cpp
+++ b/browser/components/bookmarks/src/nsForwardProxyDataSource.cpp
@@ -132,65 +132,36 @@ nsForwardProxyDataSource::GetRealSource(
     return NS_OK;
 }
 
 //----------------------------------------------------------------------
 //
 // nsISupports interface
 //
 
-NS_IMPL_ADDREF(nsForwardProxyDataSource)
-
-//
-// Use a custom Release() for the same reasons one is used in the
-// Composite DS; we have circular relationships with our child DS.
-
-NS_IMETHODIMP_(nsrefcnt)
-nsForwardProxyDataSource::Release()
-{
-    NS_PRECONDITION(PRInt32(mRefCnt) > 0, "duplicate release");
-    nsrefcnt count = --mRefCnt;
-
-    if (count == 0) {
-        NS_LOG_RELEASE(this, count, "nsForwardProxyDataSource");
-        mRefCnt = 1;
-        NS_DELETEXPCOM(this);
-        return 0;
-    }
-    else if (mDS && (PRInt32(count) == 1)) {
-        // if the count is 1, the only ref is from our nested data
-        // source, which holds on to us as an observer.
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsForwardProxyDataSource)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsForwardProxyDataSource)
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mObservers)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsForwardProxyDataSource)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDS)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mObservers)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-        // We must add 1 here because otherwise the nested releases
-        // on this object will enter this same code path.
-        ++mRefCnt;
-
-        mDS->RemoveObserver(this);
-        mDS = nsnull;
-
-        // In CompositeDataSource, there's a comment here that we call
-        // ourselves again instead of just doing a delete in case
-        // something might have added a ref count in the meantime.
-        // However, if that happens, this object will be in an
-        // inconsistent state, because we'll have removed the Observer
-        // from mDS.  Hence the assertion.
-        NS_ASSERTION(mRefCnt >= 1, "bad mRefCnt");
-        return Release();
-    }
-    else {
-        NS_LOG_RELEASE(this, count, "nsForwardProxyDataSource");
-        return count;
-    }
-}
+NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsForwardProxyDataSource,
+                                          nsIRDFInferDataSource)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsForwardProxyDataSource,
+                                           nsIRDFInferDataSource)
 
 NS_INTERFACE_MAP_BEGIN(nsForwardProxyDataSource)
     NS_INTERFACE_MAP_ENTRY(nsIRDFInferDataSource)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIRDFDataSource, nsIRDFInferDataSource)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFInferDataSource)
     NS_INTERFACE_MAP_ENTRY(nsIRDFObserver)
+    NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsForwardProxyDataSource)
 NS_INTERFACE_MAP_END
 
 //----------------------------------------------------------------------
 //
 // nsIRDFDataSource interface
 //
 
 // methods which need no proxying
--- a/browser/components/bookmarks/src/nsForwardProxyDataSource.h
+++ b/browser/components/bookmarks/src/nsForwardProxyDataSource.h
@@ -37,27 +37,30 @@
 
 #ifndef FORWARDPROXYDATASOURCE___H___
 #define FORWARDPROXYDATASOURCE___H___
 
 #include "nsCOMArray.h"
 #include "nsIRDFService.h"
 #include "nsIRDFInferDataSource.h"
 #include "nsIRDFDataSource.h"
+#include "nsCycleCollectionParticipant.h"
 
 class nsForwardProxyDataSource : public nsIRDFInferDataSource,
                                  public nsIRDFObserver
 {
 public:
     nsForwardProxyDataSource();
 
     nsresult Init(void);
 
     // nsISupports interface
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsForwardProxyDataSource,
+                                             nsIRDFInferDataSource)
 
     // nsIRDFDataSource interface
     NS_DECL_NSIRDFDATASOURCE
 
     // nsIRDFObserver interface
     NS_DECL_NSIRDFOBSERVER
 
     // nsIRDFInferDataSource interface
--- a/content/xul/templates/src/nsXULTemplateBuilder.cpp
+++ b/content/xul/templates/src/nsXULTemplateBuilder.cpp
@@ -243,18 +243,23 @@ TraverseMatchList(nsISupports* aKey, nsT
         cb->NoteXPCOMChild(match->mResult);
         match = match->mNext;
     }
 
     return PL_DHASH_NEXT;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateBuilder)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsXULTemplateBuilder)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateBuilder)
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDB)
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCompDB)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULTemplateBuilder)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDB)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCompDB)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRootResult)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mListeners)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mQueryProcessor)
     if (tmp->mMatchMap.IsInitialized())
         tmp->mMatchMap.EnumerateRead(TraverseMatchList, &cb);
     {
       PRUint32 i, count = tmp->mQuerySets.Length();
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.cpp
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.cpp
@@ -124,16 +124,17 @@ RuleToBindingTraverser(nsISupports* key,
         NS_STATIC_CAST(nsCycleCollectionTraversalCallback*, userArg);
 
     cb->NoteXPCOMChild(key);
 
     return PL_DHASH_NEXT;
 }
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULTemplateQueryProcessorRDF)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDB)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastRef)
     if (tmp->mBindingDependencies.IsInitialized()) {
         tmp->mBindingDependencies.EnumerateRead(BindingDependenciesTraverser,
                                                 &cb);
     }
     if (tmp->mMemoryElementToResultMap.IsInitialized()) {
         tmp->mMemoryElementToResultMap.EnumerateRead(MemoryElementTraverser,
                                                      &cb);
--- a/rdf/base/src/nsCompositeDataSource.cpp
+++ b/rdf/base/src/nsCompositeDataSource.cpp
@@ -71,16 +71,17 @@
 #include "nsIRDFObserver.h"
 #include "nsIRDFRemoteDataSource.h"
 #include "nsFixedSizeAllocator.h"
 #include "nsVoidArray.h"
 #include "nsCOMArray.h"
 #include "nsArrayEnumerator.h"
 #include "nsXPIDLString.h"
 #include "rdf.h"
+#include "nsCycleCollectionParticipant.h"
 
 #include "nsEnumeratorUtils.h"
 
 #ifdef NS_DEBUG
 #include "prlog.h"
 #include "prprf.h"
 #include <stdio.h>
 PRLogModuleInfo* nsRDFLog = nsnull;
@@ -100,17 +101,19 @@ class CompositeAssertionEnumeratorImpl;
 class CompositeDataSourceImpl : public nsIRDFCompositeDataSource,
                                 public nsIRDFObserver
 {
 public:
     CompositeDataSourceImpl(void);
     CompositeDataSourceImpl(char** dataSources);
 
     // nsISupports interface
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(CompositeDataSourceImpl,
+                                             nsIRDFCompositeDataSource)
 
     // nsIRDFDataSource interface
     NS_DECL_NSIRDFDATASOURCE
 
     // nsIRDFCompositeDataSource interface
     NS_DECL_NSIRDFCOMPOSITEDATASOURCE
 
     // nsIRDFObserver interface
@@ -641,87 +644,44 @@ CompositeDataSourceImpl::CompositeDataSo
 #endif
 }
 
 //----------------------------------------------------------------------
 //
 // nsISupports interface
 //
 
-NS_IMPL_THREADSAFE_ADDREF(CompositeDataSourceImpl)
-
-NS_IMETHODIMP_(nsrefcnt)
-CompositeDataSourceImpl::Release()
-{
-    // We need a special implementation of Release() because the
-    // composite datasource holds a reference to each datasource that
-    // it "composes", and each database that the composite datasource
-    // observes holds a reference _back_ to the composite datasource.
-    NS_PRECONDITION(PRInt32(mRefCnt) > 0, "duplicate release");
-    nsrefcnt count =
-      PR_AtomicDecrement(NS_REINTERPRET_CAST(PRInt32 *, &mRefCnt));
-
-    // When the number of references == the number of datasources,
-    // then we know that all that remains are the circular
-    // references from those datasources back to us. Release them.
-    if (count == 0) {
-        NS_LOG_RELEASE(this, count, "CompositeDataSourceImpl");
-        mRefCnt = 1;
-        NS_DELETEXPCOM(this);
-        return 0;
+NS_IMPL_CYCLE_COLLECTION_CLASS(CompositeDataSourceImpl)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CompositeDataSourceImpl)
+    PRUint32 i, count = tmp->mDataSources.Count();
+    for (i = count; i > 0; --i) {
+        tmp->mDataSources[i - 1]->RemoveObserver(tmp);
+        tmp->mDataSources.RemoveObjectAt(i - 1);
     }
-    else if (PRInt32(count) == mDataSources.Count()) {
-        // We must add 1 here because otherwise the nested releases
-        // on this object will enter this same code path.
-        PR_AtomicIncrement(NS_REINTERPRET_CAST(PRInt32 *, &mRefCnt));
-        
-        PRInt32 dsCount;
-        while (0 != (dsCount = mDataSources.Count())) {
-            // Take ref so it won't die before its time.
-            nsCOMPtr<nsIRDFDataSource> ds = mDataSources[dsCount-1];
-            mDataSources.RemoveObjectAt(dsCount-1);
-            ds->RemoveObserver(this);
-        }
-        // Nest into Release to deal with the one last reference we added above.
-        // We don't want to assume that we can 'delete this' because an
-        // extra reference might have been added by other code while we were 
-        // calling out.
-        NS_ASSERTION(mRefCnt >= 1, "bad mRefCnt");
-        return Release();
-    }
-    else {
-        NS_LOG_RELEASE(this, count, "CompositeDataSourceImpl");
-        return count;
-    }
-}
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mObservers);
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CompositeDataSourceImpl)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mObservers)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mDataSources)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
 
-NS_IMETHODIMP
-CompositeDataSourceImpl::QueryInterface(REFNSIID iid, void** result)
-{
-    if (! result)
-        return NS_ERROR_NULL_POINTER;
+NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(CompositeDataSourceImpl,
+                                          nsIRDFCompositeDataSource)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(CompositeDataSourceImpl,
+                                           nsIRDFCompositeDataSource)
 
-    if (iid.Equals(NS_GET_IID(nsIRDFCompositeDataSource)) ||
-        iid.Equals(NS_GET_IID(nsIRDFDataSource)) ||
-        iid.Equals(kISupportsIID)) {
-        *result = NS_STATIC_CAST(nsIRDFCompositeDataSource*, this);
-		NS_ADDREF(this);
-        return NS_OK;
-    }
-    else if (iid.Equals(NS_GET_IID(nsIRDFObserver))) {
-        *result = NS_STATIC_CAST(nsIRDFObserver*, this);
-        NS_ADDREF(this);
-        return NS_OK;
-    }
-    else {
-        *result = nsnull;
-        return NS_NOINTERFACE;
-    }
-}
-
+NS_INTERFACE_MAP_BEGIN(CompositeDataSourceImpl)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFCompositeDataSource)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFObserver)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFCompositeDataSource)
+    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFCompositeDataSource)
+    NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(CompositeDataSourceImpl)
+NS_INTERFACE_MAP_END
 
 
 //----------------------------------------------------------------------
 //
 // nsIRDFDataSource interface
 //
 
 NS_IMETHODIMP
--- a/rdf/base/src/nsInMemoryDataSource.cpp
+++ b/rdf/base/src/nsInMemoryDataSource.cpp
@@ -343,17 +343,18 @@ protected:
     InMemoryDataSource(nsISupports* aOuter);
     virtual ~InMemoryDataSource();
     nsresult Init();
 
     friend NS_IMETHODIMP
     NS_NewRDFInMemoryDataSource(nsISupports* aOuter, const nsIID& aIID, void** aResult);
 
 public:
-    NS_DECL_AGGREGATED
+    NS_DECL_CYCLE_COLLECTING_AGGREGATED
+    NS_DECL_AGGREGATED_CYCLE_COLLECTION_CLASS(InMemoryDataSource)
 
     // nsIRDFDataSource methods
     NS_DECL_NSIRDFDATASOURCE
 
     // nsIRDFInMemoryDataSource methods
     NS_DECL_NSIRDFINMEMORYDATASOURCE
 
     // nsIRDFPropagatableDataSource methods
@@ -969,23 +970,32 @@ InMemoryDataSource::DeleteForwardArcsEnt
         doomed->Release(*allocator);
     }
     return PL_DHASH_NEXT;
 }
 
 
 ////////////////////////////////////////////////////////////////////////
 
-NS_IMPL_AGGREGATED(InMemoryDataSource)
+NS_IMPL_CYCLE_COLLECTION_CLASS(InMemoryDataSource)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(InMemoryDataSource)
+    NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mObservers)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_AGGREGATED(InMemoryDataSource)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mObservers)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTING_AGGREGATED(InMemoryDataSource)
 NS_INTERFACE_MAP_BEGIN_AGGREGATED(InMemoryDataSource)
     NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
     NS_INTERFACE_MAP_ENTRY(nsIRDFInMemoryDataSource)
     NS_INTERFACE_MAP_ENTRY(nsIRDFPropagatableDataSource)
     NS_INTERFACE_MAP_ENTRY(nsIRDFPurgeableDataSource)
     NS_INTERFACE_MAP_ENTRY(rdfIDataSource)
+    NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION_AGGREGATED(InMemoryDataSource)
 NS_INTERFACE_MAP_END
 
 ////////////////////////////////////////////////////////////////////////
 
 
 #ifdef PR_LOGGING
 void
 InMemoryDataSource::LogOperation(const char* aOperation,
--- a/rdf/base/src/nsRDFXMLDataSource.cpp
+++ b/rdf/base/src/nsRDFXMLDataSource.cpp
@@ -117,16 +117,17 @@
 #include "plstr.h"
 #include "prio.h"
 #include "prthread.h"
 #include "rdf.h"
 #include "rdfutil.h"
 #include "prlog.h"
 #include "nsNameSpaceMap.h"
 #include "nsCRT.h"
+#include "nsCycleCollectionParticipant.h"
 
 #include "rdfIDataSource.h"
 
 //----------------------------------------------------------------------
 
 static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
 static NS_DEFINE_CID(kRDFServiceCID,            NS_RDFSERVICE_CID);
 
@@ -149,17 +150,17 @@ class RDFXMLDataSourceImpl : public nsIR
 protected:
     enum LoadState {
         eLoadState_Unloaded,
         eLoadState_Pending,
         eLoadState_Loading,
         eLoadState_Loaded
     };
 
-    nsIRDFDataSource*   mInner;         // OWNER
+    nsCOMPtr<nsIRDFDataSource> mInner;
     PRPackedBool        mIsWritable;    // true if the document can be written back
     PRPackedBool        mIsDirty;       // true if the document should be written back
     LoadState           mLoadState;     // what we're doing now
     nsCOMArray<nsIRDFXMLSinkObserver> mObservers;
     nsCOMPtr<nsIURI>    mURL;
     nsCOMPtr<nsIStreamListener> mListener;
     nsNameSpaceMap      mNameSpaces;
 
@@ -177,17 +178,19 @@ protected:
 
     inline PRBool IsLoading() {
         return (mLoadState == eLoadState_Pending) || 
                (mLoadState == eLoadState_Loading);
     }
 
 public:
     // nsISupports
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(RDFXMLDataSourceImpl,
+                                             nsIRDFDataSource)
 
     // nsIRDFDataSource
     NS_IMETHOD GetURI(char* *uri);
 
     NS_IMETHOD GetSource(nsIRDFResource* property,
                          nsIRDFNode* target,
                          PRBool tv,
                          nsIRDFResource** source) {
@@ -408,33 +411,32 @@ NS_NewRDFXMLDataSource(nsIRDFDataSource*
 
     NS_ADDREF(datasource);
     *aResult = datasource;
     return NS_OK;
 }
 
 
 RDFXMLDataSourceImpl::RDFXMLDataSourceImpl(void)
-    : mInner(nsnull),
-      mIsWritable(PR_TRUE),
+    : mIsWritable(PR_TRUE),
       mIsDirty(PR_FALSE),
       mLoadState(eLoadState_Unloaded)
 {
 #ifdef PR_LOGGING
     if (! gLog)
         gLog = PR_NewLogModule("nsRDFXMLDataSource");
 #endif
 }
 
 
 nsresult
 RDFXMLDataSourceImpl::Init()
 {
     nsresult rv;
-    rv = CallCreateInstance(kRDFInMemoryDataSourceCID, &mInner);
+    mInner = do_CreateInstance(kRDFInMemoryDataSourceCID, &rv);
     if (NS_FAILED(rv)) return rv;
 
     if (gRefCnt++ == 0) {
         rv = CallGetService(kRDFServiceCID, &gRDFService);
 
         NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service");
         if (NS_FAILED(rv)) return rv;
     }
@@ -451,31 +453,42 @@ RDFXMLDataSourceImpl::~RDFXMLDataSourceI
     rv = gRDFService->UnregisterDataSource(this);
 
     // Now flush contents
     rv = Flush();
 
     // Release RDF/XML sink observers
     mObservers.Clear();
 
-    NS_RELEASE(mInner);
-
     if (--gRefCnt == 0)
         NS_IF_RELEASE(gRDFService);
 }
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(RDFXMLDataSourceImpl)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_0(RDFXMLDataSourceImpl)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(RDFXMLDataSourceImpl)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInner)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_ISUPPORTS7(RDFXMLDataSourceImpl,
-                   nsIRDFDataSource,
-                   nsIRDFRemoteDataSource,
-                   nsIRDFXMLSink,
-                   nsIRDFXMLSource,
-                   nsIRequestObserver,
-                   nsIStreamListener,
-                   rdfIDataSource)
+NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(RDFXMLDataSourceImpl,
+                                          nsIRDFDataSource)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(RDFXMLDataSourceImpl,
+                                           nsIRDFDataSource)
+
+NS_INTERFACE_MAP_BEGIN(RDFXMLDataSourceImpl)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFRemoteDataSource)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFXMLSink)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFXMLSource)
+    NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
+    NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
+    NS_INTERFACE_MAP_ENTRY(rdfIDataSource)
+    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFDataSource)
+    NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(RDFXMLDataSourceImpl)
+NS_INTERFACE_MAP_END
 
 
 nsresult
 RDFXMLDataSourceImpl::BlockingParse(nsIURI* aURL, nsIStreamListener* aConsumer)
 {
     nsresult rv;
 
     // XXX I really hate the way that we're spoon-feeding this stuff
--- a/rdf/chrome/src/nsChromeUIDataSource.cpp
+++ b/rdf/chrome/src/nsChromeUIDataSource.cpp
@@ -75,40 +75,40 @@ nsChromeUIDataSource::nsChromeUIDataSour
 
 nsChromeUIDataSource::~nsChromeUIDataSource()
 {
   mRDFService->UnregisterDataSource(this);
 
   NS_IF_RELEASE(mRDFService);
 }
 
-// we require a special implementation of Release, which knows about
-// a circular strong reference
-NS_IMPL_ADDREF(nsChromeUIDataSource)
-NS_IMPL_QUERY_INTERFACE2(nsChromeUIDataSource, nsIRDFDataSource, nsIRDFObserver)
-
-NS_IMETHODIMP_(nsrefcnt)
-nsChromeUIDataSource::Release()
-{
-  NS_PRECONDITION(PRInt32(mRefCnt) > 0, "duplicate release");
-  --mRefCnt;
-  NS_LOG_RELEASE(this, mRefCnt, "nsChromeUIDataSource");
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsChromeUIDataSource)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsChromeUIDataSource)
+  if (tmp->mComposite) {
+    tmp->mComposite->RemoveObserver(tmp);
+    tmp->mComposite = nsnull;
+  }
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mObservers);
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsChromeUIDataSource)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mComposite)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mObservers)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-  // delete if the last reference is our strong circular reference
-  if (mComposite && PRInt32(mRefCnt) == 1) {
-    mComposite->RemoveObserver(this);
-    return 0;
-  }
-  else if (mRefCnt == 0) {
-    delete this;
-    return 0;
-  }
-  return mRefCnt;
-}
+NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsChromeUIDataSource,
+                                          nsIRDFDataSource)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsChromeUIDataSource,
+                                           nsIRDFDataSource)
 
+NS_INTERFACE_MAP_BEGIN(nsChromeUIDataSource)
+  NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
+  NS_INTERFACE_MAP_ENTRY(nsIRDFObserver)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFDataSource)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsChromeUIDataSource)
+NS_INTERFACE_MAP_END
 
 //----------------------------------------------------------------------
 //
 // nsIRDFDataSource interface
 //
 
 NS_IMETHODIMP
 nsChromeUIDataSource::GetURI(char** aURI)
--- a/rdf/chrome/src/nsChromeUIDataSource.h
+++ b/rdf/chrome/src/nsChromeUIDataSource.h
@@ -43,21 +43,24 @@ class nsISimpleEnumerator;
 class nsSupportsHashtable;
 class nsIRDFContainer;
 class nsIDOMWindowInternal;
 class nsIDocument;
 
 #include "nsIRDFDataSource.h"
 #include "nsIRDFObserver.h"
 #include "nsCOMArray.h"
+#include "nsCycleCollectionParticipant.h"
 
 class nsChromeUIDataSource : public nsIRDFDataSource, public nsIRDFObserver
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsChromeUIDataSource,
+                                           nsIRDFDataSource)
 
   // nsIRDFDataSource methods
   NS_DECL_NSIRDFDATASOURCE
 
   // nsIRDFObserver methods
   NS_DECL_NSIRDFOBSERVER
 
   // nsChromeUIDataSource methods:
--- a/rdf/datasource/src/nsFileSystemDataSource.cpp
+++ b/rdf/datasource/src/nsFileSystemDataSource.cpp
@@ -818,44 +818,25 @@ FileSystemDataSource::GetAllResources(ns
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 
 
 NS_IMETHODIMP
 FileSystemDataSource::AddObserver(nsIRDFObserver *n)
 {
-    NS_PRECONDITION(n != nsnull, "null ptr");
-    if (! n)
-        return NS_ERROR_NULL_POINTER;
-
-    if (! mObservers)
-    {
-        nsresult rv;
-        rv = NS_NewISupportsArray(getter_AddRefs(mObservers));
-        if (NS_FAILED(rv)) return rv;
-    }
-    mObservers->AppendElement(n);
-    return NS_OK;
+    return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 
 
 NS_IMETHODIMP
 FileSystemDataSource::RemoveObserver(nsIRDFObserver *n)
 {
-    NS_PRECONDITION(n != nsnull, "null ptr");
-    if (! n)
-        return NS_ERROR_NULL_POINTER;
-
-    if (! mObservers)
-        return NS_OK;
-
-    mObservers->RemoveElement(n);
-    return NS_OK;
+    return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 
 
 NS_IMETHODIMP
 FileSystemDataSource::GetAllCmds(nsIRDFResource* source,
                                      nsISimpleEnumerator/*<nsIRDFResource>*/** commands)
 {
--- a/rdf/datasource/src/nsFileSystemDataSource.h
+++ b/rdf/datasource/src/nsFileSystemDataSource.h
@@ -71,17 +71,16 @@ private:
     PRBool   isDirURI(nsIRDFResource* aSource);
     nsresult GetVolumeList(nsISimpleEnumerator **aResult);
     nsresult GetFolderList(nsIRDFResource *source, PRBool allowHidden, PRBool onlyFirst, nsISimpleEnumerator **aResult);
     nsresult GetName(nsIRDFResource *source, nsIRDFLiteral** aResult);
     nsresult GetURL(nsIRDFResource *source, PRBool *isFavorite, nsIRDFLiteral** aResult);
     nsresult GetFileSize(nsIRDFResource *source, nsIRDFInt** aResult);
     nsresult GetLastMod(nsIRDFResource *source, nsIRDFDate** aResult);
 
-    nsCOMPtr<nsISupportsArray> mObservers;
     nsCOMPtr<nsIRDFService>    mRDFService;
 
     // pseudo-constants
     nsCOMPtr<nsIRDFResource>       mNC_FileSystemRoot;
     nsCOMPtr<nsIRDFResource>       mNC_Child;
     nsCOMPtr<nsIRDFResource>       mNC_Name;
     nsCOMPtr<nsIRDFResource>       mNC_URL;
     nsCOMPtr<nsIRDFResource>       mNC_Icon;
--- a/rdf/datasource/src/nsLocalStore.cpp
+++ b/rdf/datasource/src/nsLocalStore.cpp
@@ -80,17 +80,16 @@ protected:
     LocalStoreImpl();
     virtual ~LocalStoreImpl();
     nsresult Init();
     nsresult LoadData();
 
     friend NS_IMETHODIMP
     NS_NewLocalStore(nsISupports* aOuter, REFNSIID aIID, void** aResult);
 
-    nsCOMPtr<nsISupportsArray> mObservers;
     nsCOMPtr<nsIRDFService>    mRDFService;
 
 public:
     // nsISupports interface
     NS_DECL_ISUPPORTS
 
     // nsILocalStore interface
 
@@ -157,33 +156,21 @@ public:
                             nsIRDFResource* aProperty,
                             nsIRDFNode* aTarget,
                             PRBool aTruthValue,
                             PRBool* hasAssertion) {
         return mInner->HasAssertion(aSource, aProperty, aTarget, aTruthValue, hasAssertion);
     }
 
     NS_IMETHOD AddObserver(nsIRDFObserver* aObserver) {
-        // Observers are _never_ notified, but we still have to play
-        // nice.
-        if (! mObservers) {
-            nsresult rv;
-            rv = NS_NewISupportsArray(getter_AddRefs(mObservers));
-            if (NS_FAILED(rv)) return rv;
-        }
-
-        mObservers->AppendElement(aObserver);
-        return NS_OK;
+        return NS_ERROR_NOT_IMPLEMENTED;
     }
 
     NS_IMETHOD RemoveObserver(nsIRDFObserver* aObserver) {
-        if (mObservers) {
-            mObservers->RemoveElement(aObserver);
-        }
-        return NS_OK;
+        return NS_ERROR_NOT_IMPLEMENTED;
     }
 
     NS_IMETHOD HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, PRBool *_retval) {
         return mInner->HasArcIn(aNode, aArc, _retval);
     }
 
     NS_IMETHOD HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, PRBool *_retval) {
         return mInner->HasArcOut(aSource, aArc, _retval);
--- a/toolkit/components/downloads/src/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/src/nsDownloadManager.cpp
@@ -1581,17 +1581,34 @@ nsXPIProgressListener::AssertProgressInf
 //   XXXben I'm making this datasource proxy its own object now and passing 
 //          IconURL requests through it so that the framework is in place by
 //          0.9 when the time comes to upgrade to the Magical World of Mork.
 //          
 //          Eventually I want to abstract away almost all direct dealings with 
 //          this datasource into functions on this object, to simplify the 
 //          code in the download manager service and front end.
 
-NS_IMPL_ISUPPORTS2(nsDownloadsDataSource, nsIRDFDataSource, nsIRDFRemoteDataSource)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDownloadsDataSource)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsDownloadsDataSource)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDownloadsDataSource)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInner)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsDownloadsDataSource,
+                                          nsIRDFDataSource)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsDownloadsDataSource,
+                                           nsIRDFDataSource)
+
+NS_INTERFACE_MAP_BEGIN(nsDownloadsDataSource)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFRemoteDataSource)
+    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFDataSource)
+    NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDownloadsDataSource)
+NS_INTERFACE_MAP_END
 
 nsresult
 nsDownloadsDataSource::LoadDataSource()
 {
   nsCOMPtr<nsIFile> downloadsFile;
   nsresult rv = NS_GetSpecialDirectory(NS_APP_DOWNLOADS_50_FILE, getter_AddRefs(downloadsFile));
   if (NS_FAILED(rv)) return rv;
 
--- a/toolkit/components/downloads/src/nsDownloadManager.h
+++ b/toolkit/components/downloads/src/nsDownloadManager.h
@@ -60,16 +60,17 @@
 #include "nsIRequest.h"
 #include "nsIObserver.h"
 #include "nsIStringBundle.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIProgressDialog.h"
 #include "nsIMIMEInfo.h"
 #include "nsITimer.h"
 #include "nsIAlertsService.h"
+#include "nsCycleCollectionParticipant.h"
 
 typedef PRInt16 DownloadState;
 typedef PRInt16 DownloadType;
 
 class nsXPIProgressListener;
 class nsDownload;
 
 class nsDownloadManager : public nsIDownloadManager,
@@ -177,17 +178,19 @@ private:
 };
 
 class nsDownloadsDataSource : public nsIRDFDataSource, 
                               public nsIRDFRemoteDataSource
 {
 public:
   NS_DECL_NSIRDFDATASOURCE
   NS_DECL_NSIRDFREMOTEDATASOURCE
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDownloadsDataSource,
+                                           nsIRDFDataSource)
 
   nsDownloadsDataSource() { };
   virtual ~nsDownloadsDataSource() { };
 
   nsresult LoadDataSource();
 
 private:
   nsCOMPtr<nsIRDFDataSource> mInner;
--- a/toolkit/components/history/src/nsGlobalHistory.cpp
+++ b/toolkit/components/history/src/nsGlobalHistory.cpp
@@ -542,29 +542,39 @@ nsGlobalHistory::~nsGlobalHistory()
 
 
 //----------------------------------------------------------------------
 //
 // nsGlobalHistory
 //
 //   nsISupports methods
 
-NS_IMPL_ADDREF(nsGlobalHistory)
-NS_IMPL_RELEASE(nsGlobalHistory)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalHistory)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalHistory)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mObservers)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGlobalHistory)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mObservers)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsGlobalHistory, nsIBrowserHistory)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsGlobalHistory, nsIBrowserHistory)
 
 NS_INTERFACE_MAP_BEGIN(nsGlobalHistory)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIGlobalHistory2, nsIGlobalHistory3)
   NS_INTERFACE_MAP_ENTRY(nsIGlobalHistory3)
   NS_INTERFACE_MAP_ENTRY(nsIBrowserHistory)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
   NS_INTERFACE_MAP_ENTRY(nsIRDFRemoteDataSource)
   NS_INTERFACE_MAP_ENTRY(nsIAutoCompleteSearch)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIBrowserHistory)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsGlobalHistory)
 NS_INTERFACE_MAP_END
 
 //----------------------------------------------------------------------
 //
 // nsGlobalHistory
 //
 //   nsIGlobalHistory2 methods
 //
@@ -2291,36 +2301,28 @@ nsGlobalHistory::HasAssertion(nsIRDFReso
 
 NS_IMETHODIMP
 nsGlobalHistory::AddObserver(nsIRDFObserver* aObserver)
 {
   NS_PRECONDITION(aObserver != nsnull, "null ptr");
   if (! aObserver)
     return NS_ERROR_NULL_POINTER;
 
-  if (! mObservers) {
-    nsresult rv;
-    rv = NS_NewISupportsArray(getter_AddRefs(mObservers));
-    if (NS_FAILED(rv)) return rv;
-  }
-  mObservers->AppendElement(aObserver);
+  mObservers.AppendObject(aObserver);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGlobalHistory::RemoveObserver(nsIRDFObserver* aObserver)
 {
   NS_PRECONDITION(aObserver != nsnull, "null ptr");
   if (! aObserver)
     return NS_ERROR_NULL_POINTER;
 
-  if (! mObservers)
-    return NS_OK;
-
-  mObservers->RemoveElement(aObserver);
+  mObservers.RemoveObject(aObserver);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsGlobalHistory::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, PRBool *result)
 {
   NS_PRECONDITION(aNode != nsnull, "null ptr");
@@ -2482,65 +2484,33 @@ nsGlobalHistory::GetAllResources(nsISimp
 
 NS_IMETHODIMP
 nsGlobalHistory::BeginUpdateBatch()
 {
   nsresult rv = NS_OK;
 
   ++mBatchesInProgress;
   
-  // we could call mObservers->EnumerateForwards() here
-  // to save the addref/release on each observer, but
-  // it's unlikely that anyone but the tree builder
-  // is observing us
-  if (mObservers) {
-    PRUint32 count;
-    rv = mObservers->Count(&count);
-    if (NS_FAILED(rv)) return rv;
-
-    for (PRInt32 i = 0; i < PRInt32(count); ++i) {
-      nsIRDFObserver* observer = NS_STATIC_CAST(nsIRDFObserver*, mObservers->ElementAt(i));
-
-      NS_ASSERTION(observer != nsnull, "null ptr");
-      if (! observer)
-        continue;
-
-      rv = observer->OnBeginUpdateBatch(this);
-      NS_RELEASE(observer);
-    }
+  PRUint32 i = mObservers.Length();
+  while (i > 0) {
+    rv = mObservers[i--]->OnBeginUpdateBatch(this);
   }
   return rv;
 }
 
 NS_IMETHODIMP
 nsGlobalHistory::EndUpdateBatch()
 {
   nsresult rv = NS_OK;
 
   --mBatchesInProgress;
 
-  // we could call mObservers->EnumerateForwards() here
-  // to save the addref/release on each observer, but
-  // it's unlikely that anyone but the tree builder
-  // is observing us
-  if (mObservers) {
-    PRUint32 count;
-    rv = mObservers->Count(&count);
-    if (NS_FAILED(rv)) return rv;
-
-    for (PRInt32 i = 0; i < PRInt32(count); ++i) {
-      nsIRDFObserver* observer = NS_STATIC_CAST(nsIRDFObserver*, mObservers->ElementAt(i));
-
-      NS_ASSERTION(observer != nsnull, "null ptr");
-      if (! observer)
-        continue;
-
-      rv = observer->OnEndUpdateBatch(this);
-      NS_RELEASE(observer);
-    }
+  PRUint32 i = mObservers.Length();
+  while (i > 0) {
+    rv = mObservers[i--]->OnEndUpdateBatch(this);
   }
   return rv;
 }
 
 
 
 ////////////////////////////////////////////////////////////////////////
 // nsIRDFRemoteDataSource
@@ -3204,91 +3174,49 @@ nsGlobalHistory::IsURLInHistory(nsIRDFRe
 }
 
 
 nsresult
 nsGlobalHistory::NotifyAssert(nsIRDFResource* aSource,
                               nsIRDFResource* aProperty,
                               nsIRDFNode* aValue)
 {
-  nsresult rv;
-
-  if (mObservers) {
-    PRUint32 count;
-    rv = mObservers->Count(&count);
-    if (NS_FAILED(rv)) return rv;
-
-    for (PRInt32 i = 0; i < PRInt32(count); ++i) {
-      nsIRDFObserver* observer = NS_STATIC_CAST(nsIRDFObserver*, mObservers->ElementAt(i));
-
-      NS_ASSERTION(observer != nsnull, "null ptr");
-      if (! observer)
-        continue;
-
-      rv = observer->OnAssert(this, aSource, aProperty, aValue);
-      NS_RELEASE(observer);
-    }
+  PRUint32 i = mObservers.Length();
+  while (i > 0) {
+    mObservers[i--]->OnAssert(this, aSource, aProperty, aValue);
   }
 
   return NS_OK;
 }
 
 
 nsresult
 nsGlobalHistory::NotifyUnassert(nsIRDFResource* aSource,
                                 nsIRDFResource* aProperty,
                                 nsIRDFNode* aValue)
 {
-  nsresult rv;
-
-  if (mObservers) {
-    PRUint32 count;
-    rv = mObservers->Count(&count);
-    if (NS_FAILED(rv)) return rv;
-
-    for (PRInt32 i = 0; i < PRInt32(count); ++i) {
-      nsIRDFObserver* observer = NS_STATIC_CAST(nsIRDFObserver*, mObservers->ElementAt(i));
-
-      NS_ASSERTION(observer != nsnull, "null ptr");
-      if (! observer)
-        continue;
-
-      rv = observer->OnUnassert(this, aSource, aProperty, aValue);
-      NS_RELEASE(observer);
-    }
+  PRUint32 i = mObservers.Length();
+  while (i > 0) {
+    mObservers[i--]->OnUnassert(this, aSource, aProperty, aValue);
   }
 
   return NS_OK;
 }
 
 
 
 nsresult
 nsGlobalHistory::NotifyChange(nsIRDFResource* aSource,
                               nsIRDFResource* aProperty,
                               nsIRDFNode* aOldValue,
                               nsIRDFNode* aNewValue)
 {
-  nsresult rv;
-
-  if (mObservers) {
-    PRUint32 count;
-    rv = mObservers->Count(&count);
-    if (NS_FAILED(rv)) return rv;
-
-    for (PRInt32 i = 0; i < PRInt32(count); ++i) {
-      nsIRDFObserver* observer = NS_STATIC_CAST(nsIRDFObserver*, mObservers->ElementAt(i));
-
-      NS_ASSERTION(observer != nsnull, "null ptr");
-      if (! observer)
-        continue;
-
-      rv = observer->OnChange(this, aSource, aProperty, aOldValue, aNewValue);
-      NS_RELEASE(observer);
-    }
+  PRUint32 i = mObservers.Length();
+  while (i > 0) {
+    mObservers[i--]->OnChange(this, aSource, aProperty, aOldValue, aNewValue);
   }
 
   return NS_OK;
 }
 
 //
 // this just generates a static list of find-style queries
 // only returns queries that currently have matches in global history
--- a/toolkit/components/history/src/nsGlobalHistory.h
+++ b/toolkit/components/history/src/nsGlobalHistory.h
@@ -56,16 +56,18 @@
 #include "nsHashtable.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsITimer.h"
 #include "nsIAutoCompleteSearch.h"
 #include "nsIAutoCompleteResult.h"
 #include "nsIAutoCompleteResultTypes.h"
 #include "nsHashSets.h"
+#include "nsCOMArray.h"
+#include "nsCycleCollectionParticipant.h"
 
 //----------------------------------------------------------------------
 //
 //  nsMdbTableEnumerator
 //
 //    An nsISimpleEnumerator implementation that returns the value of
 //    a column as an nsISupports. Allows for some simple selection.
 //
@@ -132,17 +134,19 @@ class nsGlobalHistory : nsSupportsWeakRe
                         public nsIObserver,
                         public nsIRDFDataSource,
                         public nsIRDFRemoteDataSource,
                         public nsIAutoCompleteSearch,
                         public nsIGlobalHistory3
 {
 public:
   // nsISupports methods 
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGlobalHistory,
+                                           nsIBrowserHistory)
 
   NS_DECL_NSIGLOBALHISTORY2
   NS_DECL_NSIGLOBALHISTORY3
   NS_DECL_NSIBROWSERHISTORY
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIRDFDATASOURCE
   NS_DECL_NSIRDFREMOTEDATASOURCE
   NS_DECL_NSIAUTOCOMPLETESEARCH
@@ -261,17 +265,17 @@ protected:
   nsresult SetDirty();
   
   static void fireSyncTimer(nsITimer *aTimer, void *aClosure)
   {((nsGlobalHistory *)aClosure)->Sync(); }
 
   //
   // RDF stuff
   //
-  nsCOMPtr<nsISupportsArray> mObservers;
+  nsCOMArray<nsIRDFObserver> mObservers;
   
   PRBool IsURLInHistory(nsIRDFResource* aResource);
   
   nsresult NotifyAssert(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aValue);
   nsresult NotifyUnassert(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aValue);
   nsresult NotifyChange(nsIRDFResource* aSource, nsIRDFResource* aProperty, nsIRDFNode* aOldValue, nsIRDFNode* aNewValue);
 
   //
--- a/xpcom/base/nsAgg.h
+++ b/xpcom/base/nsAgg.h
@@ -34,37 +34,50 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsAgg_h___
 #define nsAgg_h___
 
 #include "nsISupports.h"
+#include "nsCycleCollectionParticipant.h"
 
 
 ////////////////////////////////////////////////////////////////////////////////
 
-// Put this in your class's declaration:
+// Put NS_DECL_AGGREGATED or NS_DECL_CYCLE_COLLECTING_AGGREGATED in your class's
+// declaration.
 #define NS_DECL_AGGREGATED                                                  \
     NS_DECL_ISUPPORTS                                                       \
-                                                                            \
+    NS_DECL_AGGREGATED_HELPER
+
+#define NS_DECL_CYCLE_COLLECTING_AGGREGATED                                 \
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS                                      \
+    NS_DECL_AGGREGATED_HELPER
+
+#define NS_DECL_AGGREGATED_HELPER                                           \
 public:                                                                     \
                                                                             \
     /**                                                                     \
      * Returns the nsISupports pointer of the inner object (aka the         \
      * aggregatee). This pointer is really only useful to the outer object  \
      * (aka the aggregator), which can use it to hold on to the inner       \
      * object. Anything else wants the nsISupports pointer of the outer     \
      * object (gotten by QI'ing inner or outer to nsISupports). This method \
      * returns a non-addrefed pointer.                                      \
      * @return the nsISupports pointer of the inner object                  \
      */                                                                     \
     nsISupports* InnerObject(void) { return &fAggregated; }                 \
                                                                             \
+    /**                                                                     \
+     * Returns PR_TRUE if this object is part of an aggregated object.      \
+     */                                                                     \
+    PRBool IsPartOfAggregated(void) { return fOuter != InnerObject(); }     \
+                                                                            \
 private:                                                                    \
                                                                             \
     /* You must implement this operation instead of the nsISupports */      \
     /* methods. */                                                          \
     nsresult                                                                \
     AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr);       \
                                                                             \
     class Internal : public nsISupports {                                   \
@@ -80,50 +93,49 @@ private:                                
                                                                             \
     friend class Internal;                                                  \
                                                                             \
     nsISupports*        fOuter;                                             \
     Internal            fAggregated;                                        \
                                                                             \
 public:                                                                     \
 
+#define NS_DECL_AGGREGATED_CYCLE_COLLECTION_CLASS(_class)                   \
+class NS_CYCLE_COLLECTION_INNERCLASS                                        \
+ : public nsCycleCollectionParticipant                                      \
+{                                                                           \
+public:                                                                     \
+  NS_IMETHOD Unlink(nsISupports *p);                                        \
+  NS_IMETHOD Traverse(nsISupports *p,                                       \
+                      nsCycleCollectionTraversalCallback &cb);              \
+  NS_IMETHOD_(void) UnmarkPurple(nsISupports *p)                            \
+  {                                                                         \
+    Downcast(p)->UnmarkPurple();                                            \
+  }                                                                         \
+  static _class* Downcast(nsISupports* s)                                   \
+  {                                                                         \
+    return (_class*)((char*)(s) - offsetof(_class, fAggregated));           \
+  }                                                                         \
+  static nsISupports* Upcast(_class *p)                                     \
+  {                                                                         \
+    return p->InnerObject();                                                \
+  }                                                                         \
+};                                                           
 
 // Put this in your class's constructor:
 #define NS_INIT_AGGREGATED(outer)                                           \
   PR_BEGIN_MACRO                                                            \
     fOuter = outer ? outer : &fAggregated;                                  \
   PR_END_MACRO
 
 
 // Put this in your class's implementation file:
 #define NS_IMPL_AGGREGATED(_class)                                          \
-NS_IMETHODIMP                                                               \
-_class::QueryInterface(const nsIID& aIID, void** aInstancePtr)              \
-{                                                                           \
-    return fOuter->QueryInterface(aIID, aInstancePtr);                      \
-}                                                                           \
                                                                             \
-NS_IMETHODIMP_(nsrefcnt)                                                    \
-_class::AddRef(void)                                                        \
-{                                                                           \
-    return fOuter->AddRef();                                                \
-}                                                                           \
-                                                                            \
-NS_IMETHODIMP_(nsrefcnt)                                                    \
-_class::Release(void)                                                       \
-{                                                                           \
-    return fOuter->Release();                                               \
-}                                                                           \
-                                                                            \
-NS_IMETHODIMP                                                               \
-_class::Internal::QueryInterface(const nsIID& aIID, void** aInstancePtr)    \
-{                                                                           \
-    _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
-    return agg->AggregatedQueryInterface(aIID, aInstancePtr);               \
-}                                                                           \
+NS_IMPL_AGGREGATED_HELPER(_class)                                           \
                                                                             \
 NS_IMETHODIMP_(nsrefcnt)                                                    \
 _class::Internal::AddRef(void)                                              \
 {                                                                           \
     _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
     NS_PRECONDITION(PRInt32(agg->mRefCnt) >= 0, "illegal refcnt");          \
     ++agg->mRefCnt;                                                         \
     NS_LOG_ADDREF(this, agg->mRefCnt, #_class, sizeof(*this));              \
@@ -140,34 +152,165 @@ NS_IMETHODIMP_(nsrefcnt)                
     if (agg->mRefCnt == 0) {                                                \
         agg->mRefCnt = 1; /* stabilize */                                   \
         NS_DELETEXPCOM(agg);                                                \
         return 0;                                                           \
     }                                                                       \
     return agg->mRefCnt;                                                    \
 }                                                                           \
 
+#define NS_IMPL_CYCLE_COLLECTING_AGGREGATED(_class)                         \
+                                                                            \
+NS_IMPL_AGGREGATED_HELPER(_class)                                           \
+                                                                            \
+NS_IMETHODIMP_(nsrefcnt)                                                    \
+_class::Internal::AddRef(void)                                              \
+{                                                                           \
+    _class* agg = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Downcast(this);    \
+    NS_PRECONDITION(PRInt32(agg->mRefCnt) >= 0, "illegal refcnt");          \
+    NS_CheckThreadSafe(agg->_mOwningThread.GetThread(),                     \
+                       #_class " not thread-safe");                         \
+    nsrefcnt count = agg->mRefCnt.incr(this);                               \
+    NS_LOG_ADDREF(this, count, #_class, sizeof(*agg));                      \
+    return count;                                                           \
+}                                                                           \
+                                                                            \
+NS_IMETHODIMP_(nsrefcnt)                                                    \
+_class::Internal::Release(void)                                             \
+{                                                                           \
+    _class* agg = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Downcast(this);    \
+    NS_PRECONDITION(0 != agg->mRefCnt, "dup release");                      \
+    NS_CheckThreadSafe(agg->_mOwningThread.GetThread(),                     \
+                       #_class " not thread-safe");                         \
+    nsrefcnt count = agg->mRefCnt.decr(this);                               \
+    NS_LOG_RELEASE(this, count, #_class);                                   \
+    if (count == 0) {                                                       \
+        agg->mRefCnt.stabilizeForDeletion(this);                            \
+        NS_DELETEXPCOM(agg);                                                \
+        return 0;                                                           \
+    }                                                                       \
+    return count;                                                           \
+}
+
+#define NS_IMPL_AGGREGATED_HELPER(_class)                                   \
+NS_IMETHODIMP                                                               \
+_class::QueryInterface(const nsIID& aIID, void** aInstancePtr)              \
+{                                                                           \
+    return fOuter->QueryInterface(aIID, aInstancePtr);                      \
+}                                                                           \
+                                                                            \
+NS_IMETHODIMP_(nsrefcnt)                                                    \
+_class::AddRef(void)                                                        \
+{                                                                           \
+    return fOuter->AddRef();                                                \
+}                                                                           \
+                                                                            \
+NS_IMETHODIMP_(nsrefcnt)                                                    \
+_class::Release(void)                                                       \
+{                                                                           \
+    return fOuter->Release();                                               \
+}                                                                           \
+                                                                            \
+NS_IMETHODIMP                                                               \
+_class::Internal::QueryInterface(const nsIID& aIID, void** aInstancePtr)    \
+{                                                                           \
+    _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
+    return agg->AggregatedQueryInterface(aIID, aInstancePtr);               \
+}                                                                           \
+
+/**
+ * To make aggregated objects participate in cycle collection we need to enable
+ * the outer object (aggregator) to traverse/unlink the objects held by the
+ * inner object (the aggregatee). We can't just make the inner object QI'able to
+ * NS_CYCLECOLLECTIONPARTICIPANT_IID, we don't want to return the inner object's
+ * nsCycleCollectionParticipant for the outer object (which will happen if the
+ * outer object doesn't participate in cycle collection itself).
+ * NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID enables the outer object to get
+ * the inner objects nsCycleCollectionParticipant.
+ *
+ * There are three cases:
+ *   - No aggregation
+ *     QI'ing to NS_CYCLECOLLECTIONPARTICIPANT_IID will return the inner
+ *     object's nsCycleCollectionParticipant.
+ *
+ *   - Aggregation and outer object does not participate in cycle collection
+ *     QI'ing to NS_CYCLECOLLECTIONPARTICIPANT_IID will not return anything.
+ *
+ *   - Aggregation and outer object does participate in cycle collection
+ *     QI'ing to NS_CYCLECOLLECTIONPARTICIPANT_IID will return the outer
+ *     object's nsCycleCollectionParticipant. The outer object's
+ *     nsCycleCollectionParticipant can then QI the inner object to
+ *     NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID to get the inner object's
+ *     nsCycleCollectionParticipant, which it can use to traverse/unlink the
+ *     objects reachable from the inner object.
+ */
+#define NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID                        \
+{                                                                           \
+    0x32889b7e,                                                             \
+    0xe4fe,                                                                 \
+    0x43f4,                                                                 \
+    { 0x85, 0x31, 0xb5, 0x28, 0x23, 0xa2, 0xe9, 0xfc }                      \
+}
+
+/**
+ * Just holds the IID so NS_GET_IID works.
+ */
+class nsAggregatedCycleCollectionParticipant
+{
+public:
+    NS_DECLARE_STATIC_IID_ACCESSOR(NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID)
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsAggregatedCycleCollectionParticipant, 
+                              NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID)
+
 // for use with QI macros in nsISupportsUtils.h:
 
 #define NS_INTERFACE_MAP_BEGIN_AGGREGATED(_class)                           \
   NS_IMPL_AGGREGATED_QUERY_HEAD(_class)
 
+#define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_AGGREGATED(_class)          \
+  NS_IMPL_QUERY_CYCLE_COLLECTION(_class)
+
+#define NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION_AGGREGATED(_class)        \
+  NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_AGGREGATED(_class)                \
+  NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)
+
 #define NS_IMPL_AGGREGATED_QUERY_HEAD(_class)                               \
 nsresult                                                                    \
 _class::AggregatedQueryInterface(REFNSIID aIID, void** aInstancePtr)        \
 {                                                                           \
   NS_ASSERTION(aInstancePtr,                                                \
                "AggregatedQueryInterface requires a non-NULL result ptr!"); \
   if ( !aInstancePtr )                                                      \
     return NS_ERROR_NULL_POINTER;                                           \
   nsISupports* foundInterface;                                              \
   if ( aIID.Equals(NS_GET_IID(nsISupports)) )                               \
     foundInterface = InnerObject();                                         \
   else
 
+#define NS_IMPL_AGGREGATED_QUERY_CYCLE_COLLECTION(_class)                   \
+  if (aIID.Equals(IsPartOfAggregated() ?                                    \
+                  NS_GET_IID(nsCycleCollectionParticipant) :                \
+                  NS_GET_IID(nsAggregatedCycleCollectionParticipant)))      \
+    foundInterface = & NS_CYCLE_COLLECTION_NAME(_class);                    \
+  else
+
+#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_AGGREGATED(_class)          \
+  NS_IMETHODIMP                                                             \
+  NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse                           \
+                         (nsISupports *p,                                   \
+                          nsCycleCollectionTraversalCallback &cb)           \
+  {                                                                         \
+    NS_ASSERTION(CheckForRightISupports(p),                                 \
+                 "not the nsISupports pointer we expect");                  \
+    _class *tmp = NS_STATIC_CAST(_class*, Downcast(p));                     \
+    if (!tmp->IsPartOfAggregated())                                         \
+        NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class)
+
 #define NS_GENERIC_AGGREGATED_CONSTRUCTOR(_InstanceClass)                   \
 static NS_METHOD                                                            \
 _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID,             \
                             void **aResult)                                 \
 {                                                                           \
     *aResult = nsnull;                                                      \
                                                                             \
     NS_ENSURE_PROPER_AGGREGATION(aOuter, aIID);                             \
--- a/xpfe/components/intl/nsCharsetMenu.cpp
+++ b/xpfe/components/intl/nsCharsetMenu.cpp
@@ -60,16 +60,17 @@
 #include "nsIObserver.h"
 #include "nsStringEnumerator.h"
 #include "nsVoidArray.h"
 #include "nsIObserverService.h"
 #include "nsIRequestObserver.h"
 #include "nsITimelineService.h"
 #include "nsCRT.h"
 #include "prmem.h"
+#include "nsCycleCollectionParticipant.h"
 
 //----------------------------------------------------------------------------
 // Global functions and data [declaration]
 
 static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
 static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
 static NS_DEFINE_CID(kRDFContainerUtilsCID, NS_RDFCONTAINERUTILS_CID);
 static NS_DEFINE_CID(kRDFContainerCID, NS_RDFCONTAINER_CID);
@@ -148,17 +149,18 @@ public:
  *
  * God, our GUI programming disgusts me.
  *
  * @created         23/Nov/1999
  * @author  Catalin Rotaru [CATA]
  */
 class nsCharsetMenu : public nsIRDFDataSource, public nsICurrentCharsetListener
 {
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsCharsetMenu, nsIRDFDataSource)
 
 private:
   static nsIRDFResource * kNC_BrowserAutodetMenuRoot;
   static nsIRDFResource * kNC_BrowserCharsetMenuRoot;
   static nsIRDFResource * kNC_BrowserMoreCharsetMenuRoot;
   static nsIRDFResource * kNC_BrowserMore1CharsetMenuRoot;
   static nsIRDFResource * kNC_BrowserMore2CharsetMenuRoot;
   static nsIRDFResource * kNC_BrowserMore3CharsetMenuRoot;
@@ -460,17 +462,30 @@ NS_IMETHODIMP nsCharsetMenuObserver::Obs
   NS_TIMELINE_STOP_TIMER("nsCharsetMenu:Observe");
   NS_TIMELINE_MARK_TIMER("nsCharsetMenu:Observe");
   return rv;
 }
 
 //----------------------------------------------------------------------------
 // Class nsCharsetMenu [implementation]
 
-NS_IMPL_ISUPPORTS2(nsCharsetMenu, nsIRDFDataSource, nsICurrentCharsetListener)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsCharsetMenu)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsCharsetMenu)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCharsetMenu)
+  cb.NoteXPCOMChild(nsCharsetMenu::mInner);
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsCharsetMenu, nsIRDFDataSource)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsCharsetMenu, nsIRDFDataSource)
+NS_INTERFACE_MAP_BEGIN(nsCharsetMenu)
+  NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
+  NS_INTERFACE_MAP_ENTRY(nsICurrentCharsetListener)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRDFDataSource)
+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsCharsetMenu)
+NS_INTERFACE_MAP_END
 
 nsIRDFDataSource * nsCharsetMenu::mInner = NULL;
 nsIRDFResource * nsCharsetMenu::kNC_BrowserAutodetMenuRoot = NULL;
 nsIRDFResource * nsCharsetMenu::kNC_BrowserCharsetMenuRoot = NULL;
 nsIRDFResource * nsCharsetMenu::kNC_BrowserMoreCharsetMenuRoot = NULL;
 nsIRDFResource * nsCharsetMenu::kNC_BrowserMore1CharsetMenuRoot = NULL;
 nsIRDFResource * nsCharsetMenu::kNC_BrowserMore2CharsetMenuRoot = NULL;
 nsIRDFResource * nsCharsetMenu::kNC_BrowserMore3CharsetMenuRoot = NULL;
--- a/xpfe/components/related/src/nsRelatedLinksHandler.cpp
+++ b/xpfe/components/related/src/nsRelatedLinksHandler.cpp
@@ -653,17 +653,33 @@ RelatedLinksHandlerImpl::Init()
 
 	mInner = do_CreateInstance(kRDFInMemoryDataSourceCID, &rv);
 	return rv;
 }
 
 
 // nsISupports interface
 
-NS_IMPL_ISUPPORTS2(RelatedLinksHandlerImpl, nsIRelatedLinksHandler, nsIRDFDataSource)
+NS_IMPL_CYCLE_COLLECTION_CLASS(RelatedLinksHandlerImpl)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_0(RelatedLinksHandlerImpl)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(RelatedLinksHandlerImpl)
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInner)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(RelatedLinksHandlerImpl,
+                                          nsIRelatedLinksHandler)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(RelatedLinksHandlerImpl,
+                                           nsIRelatedLinksHandler)
+
+NS_INTERFACE_MAP_BEGIN(RelatedLinksHandlerImpl)
+    NS_INTERFACE_MAP_ENTRY(nsIRelatedLinksHandler)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
+    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRelatedLinksHandler)
+    NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(RelatedLinksHandlerImpl)
+NS_INTERFACE_MAP_END
 
 // nsIRelatedLinksHandler interface
 
 NS_IMETHODIMP
 RelatedLinksHandlerImpl::GetURL(char** aURL)
 {
 	NS_PRECONDITION(aURL != nsnull, "null ptr");
 	if (! aURL)
--- a/xpfe/components/related/src/nsRelatedLinksHandlerImpl.h
+++ b/xpfe/components/related/src/nsRelatedLinksHandlerImpl.h
@@ -39,16 +39,17 @@
 #define relatedlinkshandler____h____
 
 #include "nsString.h"
 #include "nsIRDFService.h"
 #include "nsIRelatedLinksHandler.h"
 #include "nsIRDFResource.h"
 #include "nsCOMPtr.h"
 #include "nsIRDFDataSource.h"
+#include "nsCycleCollectionParticipant.h"
 
 ////////////////////////////////////////////////////////////////////////
 // RelatedLinksHandlerImpl
 
 class RelatedLinksHandlerImpl : public nsIRelatedLinksHandler,
 				public nsIRDFDataSource
 {
 private:
@@ -66,14 +67,16 @@ private:
 	nsCOMPtr<nsIRDFDataSource> mInner;
 public:
 
 				RelatedLinksHandlerImpl();
 	virtual		~RelatedLinksHandlerImpl();
 	nsresult	Init();
 
 
-	NS_DECL_ISUPPORTS
+        NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+        NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(RelatedLinksHandlerImpl,
+                                                 nsIRelatedLinksHandler)
 	NS_DECL_NSIRELATEDLINKSHANDLER
 	NS_DECL_NSIRDFDATASOURCE
 };
 
 #endif // relatedlinkshandler____h____
--- a/xpfe/components/search/src/nsLocalSearchService.cpp
+++ b/xpfe/components/search/src/nsLocalSearchService.cpp
@@ -880,49 +880,25 @@ LocalSearchDataSource::GetAllResources(n
 	return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 
 
 NS_IMETHODIMP
 LocalSearchDataSource::AddObserver(nsIRDFObserver *n)
 {
-	NS_PRECONDITION(n != nsnull, "null ptr");
-	if (! n)
-		return NS_ERROR_NULL_POINTER;
-
-	if (! mObservers)
-	{
-		nsresult	rv;
-		rv = NS_NewISupportsArray(getter_AddRefs(mObservers));
-		if (NS_FAILED(rv)) return rv;
-	}
-	return mObservers->AppendElement(n) ? NS_OK : NS_ERROR_FAILURE;
+	return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 
 
 NS_IMETHODIMP
 LocalSearchDataSource::RemoveObserver(nsIRDFObserver *n)
 {
-	NS_PRECONDITION(n != nsnull, "null ptr");
-	if (! n)
-		return NS_ERROR_NULL_POINTER;
-
-	if (! mObservers)
-		return(NS_OK);
-
-#ifdef DEBUG
-	PRBool ok =
-#endif
-	mObservers->RemoveElement(n);
-
-	NS_ASSERTION(ok, "observer not present");
-
-	return(NS_OK);
+	return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 
 
 NS_IMETHODIMP
 LocalSearchDataSource::GetAllCmds(nsIRDFResource* source, nsISimpleEnumerator/*<nsIRDFResource>*/** commands)
 {
 	return(NS_NewEmptyEnumerator(commands));
--- a/xpfe/components/search/src/nsLocalSearchService.h
+++ b/xpfe/components/search/src/nsLocalSearchService.h
@@ -51,18 +51,16 @@ typedef	struct	_findTokenStruct
 	const char		*token;
 	nsString	    value;
 } findTokenStruct, *findTokenPtr;
 
 
 class LocalSearchDataSource : public nsIRDFDataSource
 {
 private:
-	nsCOMPtr<nsISupportsArray> mObservers;
-
 	static PRInt32		gRefCnt;
 
     // pseudo-constants
 	static nsIRDFResource	*kNC_Child;
 	static nsIRDFResource	*kNC_Name;
 	static nsIRDFResource	*kNC_URL;
 	static nsIRDFResource	*kNC_FindObject;
 	static nsIRDFResource	*kNC_pulse;
--- a/xpfe/components/windowds/nsWindowDataSource.cpp
+++ b/xpfe/components/windowds/nsWindowDataSource.cpp
@@ -124,54 +124,36 @@ nsWindowDataSource::Observe(nsISupports 
         // to us
         mContainer = nsnull;
         mInner = nsnull;
     }
 
     return NS_OK;
 }
 
-#if 0
-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;
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsWindowDataSource)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsWindowDataSource)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsWindowDataSource)
+    // XXX mContainer?
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInner)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-		nsIRDFDataSource* tmp = mInner;
-		mInner = nsnull;
-		NS_IF_RELEASE(tmp);
-		return(0);
-	}
-	else if (mRefCnt == 0)
-	{
-		mRefCnt = 1;
-		delete this;
-		return(0);
-	}
-	return(mRefCnt);
-}
+NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsWindowDataSource,
+                                          nsIObserver)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsWindowDataSource,
+                                           nsIObserver)
 
-#endif
-
-
-NS_IMPL_ISUPPORTS4(nsWindowDataSource,
-                   nsIObserver,
-                   nsIWindowMediatorListener,
-                   nsIWindowDataSource,
-                   nsIRDFDataSource)
+NS_INTERFACE_MAP_BEGIN(nsWindowDataSource)
+    NS_INTERFACE_MAP_ENTRY(nsIObserver)
+    NS_INTERFACE_MAP_ENTRY(nsIWindowMediatorListener)
+    NS_INTERFACE_MAP_ENTRY(nsIWindowDataSource)
+    NS_INTERFACE_MAP_ENTRY(nsIRDFDataSource)
+    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
+    NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsWindowDataSource)
+NS_INTERFACE_MAP_END
 
 // nsIWindowMediatorListener implementation
 // handle notifications from the window mediator and reflect them into
 // RDF
 
 /* void onWindowTitleChange (in nsIXULWindow window, in wstring newTitle); */
 NS_IMETHODIMP
 nsWindowDataSource::OnWindowTitleChange(nsIXULWindow *window,
--- a/xpfe/components/windowds/nsWindowDataSource.h
+++ b/xpfe/components/windowds/nsWindowDataSource.h
@@ -41,16 +41,17 @@
 #include "nsIRDFDataSource.h"
 #include "nsIWindowMediatorListener.h"
 #include "nsIWindowDataSource.h"
 #include "nsIObserver.h"
 
 #include "nsIRDFService.h"
 #include "nsIRDFContainer.h"
 #include "nsHashtable.h"
+#include "nsCycleCollectionParticipant.h"
 
 // {C744CA3D-840B-460a-8D70-7CE63C51C958}
 #define NS_WINDOWDATASOURCE_CID \
 { 0xc744ca3d, 0x840b, 0x460a, \
  { 0x8d, 0x70, 0x7c, 0xe6, 0x3c, 0x51, 0xc9, 0x58 } }
 
 
 class nsWindowDataSource : public nsIRDFDataSource,
@@ -59,17 +60,19 @@ class nsWindowDataSource : public nsIRDF
                            public nsIWindowDataSource
 {
  public:
     nsWindowDataSource() { }
     virtual ~nsWindowDataSource();
 
     nsresult Init();
     
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsWindowDataSource,
+                                             nsIRDFDataSource)
     NS_DECL_NSIOBSERVER
     NS_DECL_NSIWINDOWMEDIATORLISTENER
     NS_DECL_NSIWINDOWDATASOURCE
     NS_DECL_NSIRDFDATASOURCE
 
  private:
 
     // mapping of window -> RDF resource