Bug 37795 - "Move nsCategoryCache to the XPCOM Glue". nsCategoryCache was initially created as part of
Bug 315598 by Christian Biesinger <cbiesinger@gmx.at>. r=bsmedberg.
--- a/xpcom/components/Makefile.in
+++ b/xpcom/components/Makefile.in
@@ -48,26 +48,24 @@ LIBRARY_NAME = xpcomcomponents_s
GRE_MODULE = 1
MOZILLA_INTERNAL_API = 1
REQUIRES = string \
$(NULL)
CPPSRCS = \
nsCategoryManager.cpp \
- nsCategoryCache.cpp \
nsComponentManager.cpp \
nsNativeComponentLoader.cpp \
nsStaticComponentLoader.cpp \
nsServiceManagerObsolete.cpp \
$(NULL)
EXPORTS = \
nsCategoryManagerUtils.h \
- nsCategoryCache.h \
nsIServiceManagerObsolete.h \
nsModule.h \
nsObsoleteModuleLoading.h \
$(NULL)
XPIDLSRCS = \
nsIModuleLoader.idl \
nsIComponentManagerObsolete.idl \
deleted file mode 100644
--- a/xpcom/components/nsCategoryCache.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-/* vim:set st=2 sts=2 ts=2 et cin: */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is a cache for services in a category.
- *
- * The Initial Developer of the Original Code is
- * Christian Biesinger <cbiesinger@web.de>.
- * Portions created by the Initial Developer are Copyright (C) 2005
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsIObserverService.h"
-#include "nsISupportsPrimitives.h"
-
-#include "nsXPCOMCID.h"
-#include "nsObserverService.h"
-
-#include "nsCategoryCache.h"
-
-nsCategoryObserver::nsCategoryObserver(const char* aCategory,
- nsCategoryListener* aListener)
- : mListener(nsnull), mCategory(aCategory)
-{
- if (!mHash.Init()) {
- // OOM
- return;
- }
-
- mListener = aListener;
-
- // First, enumerate the currently existing entries
- nsCOMPtr<nsICategoryManager> catMan =
- do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
- if (!catMan)
- return;
-
- nsCOMPtr<nsISimpleEnumerator> enumerator;
- nsresult rv = catMan->EnumerateCategory(aCategory,
- getter_AddRefs(enumerator));
- if (NS_FAILED(rv))
- return;
-
- nsCOMPtr<nsISupports> entry;
- while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(entry)))) {
- nsCOMPtr<nsISupportsCString> entryName = do_QueryInterface(entry, &rv);
-
- if (NS_SUCCEEDED(rv)) {
- nsCAutoString categoryEntry;
- rv = entryName->GetData(categoryEntry);
-
- nsXPIDLCString entryValue;
- catMan->GetCategoryEntry(aCategory,
- categoryEntry.get(),
- getter_Copies(entryValue));
-
- if (NS_SUCCEEDED(rv)) {
- mHash.Put(categoryEntry, entryValue);
- mListener->EntryAdded(entryValue);
- }
- }
- }
-
- // Now, listen for changes
- nsCOMPtr<nsIObserverService> serv =
- do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
- if (!serv)
- return;
-
- serv->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
-
- serv->AddObserver(this, NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID, PR_FALSE);
- serv->AddObserver(this, NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID, PR_FALSE);
- serv->AddObserver(this, NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID, PR_FALSE);
-}
-
-nsCategoryObserver::~nsCategoryObserver() {
-}
-
-NS_IMPL_ISUPPORTS1(nsCategoryObserver, nsIObserver)
-
-void
-nsCategoryObserver::ListenerDied() {
- mListener = nsnull;
-
- nsCOMPtr<nsIObserverService> serv =
- do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
- if (!serv)
- return;
-
- serv->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
-
- serv->RemoveObserver(this, NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID);
- serv->RemoveObserver(this, NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID);
- serv->RemoveObserver(this, NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID);
-}
-
-NS_IMETHODIMP
-nsCategoryObserver::Observe(nsISupports* aSubject, const char* aTopic,
- const PRUnichar* aData) {
- if (!mListener)
- return NS_OK;
-
- if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
- mHash.Clear();
- mListener->CategoryCleared();
- return NS_OK;
- }
-
- if (!aData || !nsDependentString(aData).EqualsASCII(mCategory.get()))
- return NS_OK;
-
- nsCAutoString str;
- nsCOMPtr<nsISupportsCString> strWrapper(do_QueryInterface(aSubject));
- if (strWrapper)
- strWrapper->GetData(str);
-
- if (strcmp(aTopic, NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID) == 0) {
- nsCOMPtr<nsICategoryManager> catMan =
- do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
- if (!catMan)
- return NS_OK;
-
- nsXPIDLCString entryValue;
- catMan->GetCategoryEntry(mCategory.get(),
- str.get(),
- getter_Copies(entryValue));
-
- mHash.Put(str, entryValue);
- mListener->EntryAdded(entryValue);
- } else if (strcmp(aTopic, NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID) == 0) {
- nsCAutoString val;
- if (mHash.Get(str, &val)) {
- mHash.Remove(str);
- mListener->EntryRemoved(val);
- }
- } else if (strcmp(aTopic, NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID) == 0) {
- mHash.Clear();
- mListener->CategoryCleared();
- }
- return NS_OK;
-}
deleted file mode 100644
--- a/xpcom/components/nsCategoryCache.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is a cache for services in a category.
- *
- * The Initial Developer of the Original Code is
- * Christian Biesinger <cbiesinger@web.de>.
- * Portions created by the Initial Developer are Copyright (C) 2005
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nsCategoryCache_h_
-#define nsCategoryCache_h_
-
-#include "nsICategoryManager.h"
-#include "nsIObserver.h"
-#include "nsISimpleEnumerator.h"
-#include "nsISupportsPrimitives.h"
-
-#include "nsServiceManagerUtils.h"
-
-#include "nsAutoPtr.h"
-#include "nsCOMArray.h"
-#include "nsDataHashtable.h"
-
-#include "nsXPCOM.h"
-
-class NS_NO_VTABLE nsCategoryListener {
- protected:
- // no virtual destructor (people shouldn't delete through an
- // nsCategoryListener pointer)
- ~nsCategoryListener() {}
-
- public:
- virtual void EntryAdded(const nsCString& aValue) = 0;
- virtual void EntryRemoved(const nsCString& aValue) = 0;
- virtual void CategoryCleared() = 0;
-};
-
-class NS_COM nsCategoryObserver : public nsIObserver {
- public:
- nsCategoryObserver(const char* aCategory,
- nsCategoryListener* aCategoryListener);
- ~nsCategoryObserver();
-
- void ListenerDied();
-
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
- private:
- nsDataHashtable<nsCStringHashKey, nsCString> mHash;
- nsCategoryListener* mListener;
- nsCString mCategory;
-};
-
-/**
- * This is a helper class that caches services that are registered in a certain
- * category. The intended usage is that a service stores a variable of type
- * nsCategoryCache<nsIFoo> in a member variable, where nsIFoo is the interface
- * that these services should implement. The constructor of this class should
- * then get the name of the category.
- */
-template<class T>
-class nsCategoryCache : protected nsCategoryListener {
- public:
- explicit nsCategoryCache(const char* aCategory);
- ~nsCategoryCache() { if (mObserver) mObserver->ListenerDied(); }
-
- const nsCOMArray<T>& GetEntries() const { return mEntries; }
- protected:
- virtual void EntryAdded(const nsCString& aValue);
- virtual void EntryRemoved(const nsCString& aValue);
- virtual void CategoryCleared();
- private:
- friend class CategoryObserver;
-
- // Not to be implemented
- nsCategoryCache(const nsCategoryCache<T>&);
-
- nsCOMArray<T> mEntries;
- nsRefPtr<nsCategoryObserver> mObserver;
-};
-
-// -----------------------------------
-// Implementation
-
-template<class T>
-nsCategoryCache<T>::nsCategoryCache(const char* aCategory)
-{
- mObserver = new nsCategoryObserver(aCategory, this);
-}
-
-template<class T>
-void nsCategoryCache<T>::EntryAdded(const nsCString& aValue) {
- nsCOMPtr<T> catEntry = do_GetService(aValue.get());
- if (catEntry)
- mEntries.AppendObject(catEntry);
-}
-
-template<class T>
-void nsCategoryCache<T>::EntryRemoved(const nsCString& aValue) {
- nsCOMPtr<T> catEntry = do_GetService(aValue.get());
- if (catEntry)
- mEntries.RemoveObject(catEntry);
-}
-
-template<class T>
-void nsCategoryCache<T>::CategoryCleared() {
- mEntries.Clear();
-}
-
-#endif
--- a/xpcom/ds/nsObserverService.h
+++ b/xpcom/ds/nsObserverService.h
@@ -37,17 +37,16 @@
#ifndef nsObserverService_h___
#define nsObserverService_h___
#include "nsIObserverService.h"
#include "nsObserverList.h"
#include "nsTHashtable.h"
-#define NS_OBSERVERSERVICE_CONTRACTID "@mozilla.org/observer-service;1"
#define NS_OBSERVERSERVICE_CLASSNAME "Observer Service"
// {D07F5195-E3D1-11d2-8ACD-00105A1B8860}
#define NS_OBSERVERSERVICE_CID \
{ 0xd07f5195, 0xe3d1, 0x11d2, { 0x8a, 0xcd, 0x0, 0x10, 0x5a, 0x1b, 0x88, 0x60 } }
class nsObserverService : public nsIObserverService {
public:
--- a/xpcom/glue/Makefile.in
+++ b/xpcom/glue/Makefile.in
@@ -69,16 +69,17 @@ CPPSRCS = \
$(NULL)
SDK_HEADERS = \
pldhash.h \
nsArrayEnumerator.h \
nsArrayUtils.h \
nsAutoLock.h \
nsBaseHashtable.h \
+ nsCategoryCache.h \
nsCOMArray.h \
nsCRTGlue.h \
nsClassHashtable.h \
nsDataHashtable.h \
nsEnumeratorUtils.h \
nsHashKeys.h \
nsINIParser.h \
nsInterfaceHashtable.h \
new file mode 100644
--- /dev/null
+++ b/xpcom/glue/nsCategoryCache.cpp
@@ -0,0 +1,167 @@
+/* vim:set st=2 sts=2 ts=2 et cin: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is a cache for services in a category.
+ *
+ * The Initial Developer of the Original Code is
+ * Christian Biesinger <cbiesinger@web.de>.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIObserverService.h"
+#include "nsISupportsPrimitives.h"
+
+#include "nsXPCOMCID.h"
+
+#include "nsCategoryCache.h"
+
+nsCategoryObserver::nsCategoryObserver(const char* aCategory,
+ nsCategoryListener* aListener)
+ : mListener(nsnull), mCategory(aCategory)
+{
+ if (!mHash.Init()) {
+ // OOM
+ return;
+ }
+
+ mListener = aListener;
+
+ // First, enumerate the currently existing entries
+ nsCOMPtr<nsICategoryManager> catMan =
+ do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
+ if (!catMan)
+ return;
+
+ nsCOMPtr<nsISimpleEnumerator> enumerator;
+ nsresult rv = catMan->EnumerateCategory(aCategory,
+ getter_AddRefs(enumerator));
+ if (NS_FAILED(rv))
+ return;
+
+ nsCOMPtr<nsISupports> entry;
+ while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(entry)))) {
+ nsCOMPtr<nsISupportsCString> entryName = do_QueryInterface(entry, &rv);
+
+ if (NS_SUCCEEDED(rv)) {
+ nsCAutoString categoryEntry;
+ rv = entryName->GetData(categoryEntry);
+
+ nsCString entryValue;
+ catMan->GetCategoryEntry(aCategory,
+ categoryEntry.get(),
+ getter_Copies(entryValue));
+
+ if (NS_SUCCEEDED(rv)) {
+ mHash.Put(categoryEntry, entryValue);
+ mListener->EntryAdded(entryValue);
+ }
+ }
+ }
+
+ // Now, listen for changes
+ nsCOMPtr<nsIObserverService> serv =
+ do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
+ if (!serv)
+ return;
+
+ serv->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
+
+ serv->AddObserver(this, NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID, PR_FALSE);
+ serv->AddObserver(this, NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID, PR_FALSE);
+ serv->AddObserver(this, NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID, PR_FALSE);
+}
+
+nsCategoryObserver::~nsCategoryObserver() {
+}
+
+NS_IMPL_ISUPPORTS1(nsCategoryObserver, nsIObserver)
+
+void
+nsCategoryObserver::ListenerDied() {
+ mListener = nsnull;
+
+ nsCOMPtr<nsIObserverService> serv =
+ do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
+ if (!serv)
+ return;
+
+ serv->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
+
+ serv->RemoveObserver(this, NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID);
+ serv->RemoveObserver(this, NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID);
+ serv->RemoveObserver(this, NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID);
+}
+
+NS_IMETHODIMP
+nsCategoryObserver::Observe(nsISupports* aSubject, const char* aTopic,
+ const PRUnichar* aData) {
+ if (!mListener)
+ return NS_OK;
+
+ if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
+ mHash.Clear();
+ mListener->CategoryCleared();
+ return NS_OK;
+ }
+
+ if (!aData ||
+ !nsDependentString(aData).Equals(NS_ConvertASCIItoUTF16(mCategory)))
+ return NS_OK;
+
+ nsCAutoString str;
+ nsCOMPtr<nsISupportsCString> strWrapper(do_QueryInterface(aSubject));
+ if (strWrapper)
+ strWrapper->GetData(str);
+
+ if (strcmp(aTopic, NS_XPCOM_CATEGORY_ENTRY_ADDED_OBSERVER_ID) == 0) {
+ nsCOMPtr<nsICategoryManager> catMan =
+ do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
+ if (!catMan)
+ return NS_OK;
+
+ nsCString entryValue;
+ catMan->GetCategoryEntry(mCategory.get(),
+ str.get(),
+ getter_Copies(entryValue));
+
+ mHash.Put(str, entryValue);
+ mListener->EntryAdded(entryValue);
+ } else if (strcmp(aTopic, NS_XPCOM_CATEGORY_ENTRY_REMOVED_OBSERVER_ID) == 0) {
+ nsCAutoString val;
+ if (mHash.Get(str, &val)) {
+ mHash.Remove(str);
+ mListener->EntryRemoved(val);
+ }
+ } else if (strcmp(aTopic, NS_XPCOM_CATEGORY_CLEARED_OBSERVER_ID) == 0) {
+ mHash.Clear();
+ mListener->CategoryCleared();
+ }
+ return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/xpcom/glue/nsCategoryCache.h
@@ -0,0 +1,137 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is a cache for services in a category.
+ *
+ * The Initial Developer of the Original Code is
+ * Christian Biesinger <cbiesinger@web.de>.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsCategoryCache_h_
+#define nsCategoryCache_h_
+
+#include "nsICategoryManager.h"
+#include "nsIObserver.h"
+#include "nsISimpleEnumerator.h"
+#include "nsISupportsPrimitives.h"
+
+#include "nsServiceManagerUtils.h"
+
+#include "nsAutoPtr.h"
+#include "nsCOMArray.h"
+#include "nsDataHashtable.h"
+
+#include "nsXPCOM.h"
+
+class NS_NO_VTABLE nsCategoryListener {
+ protected:
+ // no virtual destructor (people shouldn't delete through an
+ // nsCategoryListener pointer)
+ ~nsCategoryListener() {}
+
+ public:
+ virtual void EntryAdded(const nsCString& aValue) = 0;
+ virtual void EntryRemoved(const nsCString& aValue) = 0;
+ virtual void CategoryCleared() = 0;
+};
+
+class NS_COM_GLUE nsCategoryObserver : public nsIObserver {
+ public:
+ nsCategoryObserver(const char* aCategory,
+ nsCategoryListener* aCategoryListener);
+ ~nsCategoryObserver();
+
+ void ListenerDied();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIOBSERVER
+ private:
+ nsDataHashtable<nsCStringHashKey, nsCString> mHash;
+ nsCategoryListener* mListener;
+ nsCString mCategory;
+};
+
+/**
+ * This is a helper class that caches services that are registered in a certain
+ * category. The intended usage is that a service stores a variable of type
+ * nsCategoryCache<nsIFoo> in a member variable, where nsIFoo is the interface
+ * that these services should implement. The constructor of this class should
+ * then get the name of the category.
+ */
+template<class T>
+class nsCategoryCache : protected nsCategoryListener {
+ public:
+ explicit nsCategoryCache(const char* aCategory);
+ ~nsCategoryCache() { if (mObserver) mObserver->ListenerDied(); }
+
+ const nsCOMArray<T>& GetEntries() const { return mEntries; }
+ protected:
+ virtual void EntryAdded(const nsCString& aValue);
+ virtual void EntryRemoved(const nsCString& aValue);
+ virtual void CategoryCleared();
+ private:
+ friend class CategoryObserver;
+
+ // Not to be implemented
+ nsCategoryCache(const nsCategoryCache<T>&);
+
+ nsCOMArray<T> mEntries;
+ nsRefPtr<nsCategoryObserver> mObserver;
+};
+
+// -----------------------------------
+// Implementation
+
+template<class T>
+nsCategoryCache<T>::nsCategoryCache(const char* aCategory)
+{
+ mObserver = new nsCategoryObserver(aCategory, this);
+}
+
+template<class T>
+void nsCategoryCache<T>::EntryAdded(const nsCString& aValue) {
+ nsCOMPtr<T> catEntry = do_GetService(aValue.get());
+ if (catEntry)
+ mEntries.AppendObject(catEntry);
+}
+
+template<class T>
+void nsCategoryCache<T>::EntryRemoved(const nsCString& aValue) {
+ nsCOMPtr<T> catEntry = do_GetService(aValue.get());
+ if (catEntry)
+ mEntries.RemoveObject(catEntry);
+}
+
+template<class T>
+void nsCategoryCache<T>::CategoryCleared() {
+ mEntries.Clear();
+}
+
+#endif
--- a/xpcom/glue/objs.mk
+++ b/xpcom/glue/objs.mk
@@ -38,16 +38,17 @@ XPCOM_GLUE_SRC_LCSRCS = \
pldhash.c \
$(NULL)
XPCOM_GLUE_SRC_CSRCS = $(addprefix $(topsrcdir)/xpcom/glue/, $(XPCOM_GLUE_SRC_LCSRCS))
XPCOM_GLUE_SRC_LCPPSRCS = \
nsArrayEnumerator.cpp \
nsArrayUtils.cpp \
+ nsCategoryCache.cpp \
nsCOMPtr.cpp \
nsCOMArray.cpp \
nsCRTGlue.cpp \
nsComponentManagerUtils.cpp \
nsEnumeratorUtils.cpp \
nsID.cpp \
nsIInterfaceRequestorUtils.cpp \
nsINIParser.cpp \