diff --git a/mozilla/xpcom/components/nsIServiceManager.h b/mozilla/xpcom/components/nsIServiceManager.h index a6c9453632d..3462765225a 100644 --- a/mozilla/xpcom/components/nsIServiceManager.h +++ b/mozilla/xpcom/components/nsIServiceManager.h @@ -286,6 +286,36 @@ do_GetService( const char* aProgID, nsISupports* aServiceManager, nsresult* erro return nsGetServiceByProgID(aProgID, aServiceManager, error); } +class NS_COM nsGetServiceFromCategory : public nsCOMPtr_helper +{ +public: + nsGetServiceFromCategory(const char* aCategory, const char* aEntry, + nsISupports* aServiceManager, + nsresult* aErrorPtr) + : mCategory(aCategory), + mEntry(aEntry), + mServiceManager( do_QueryInterface(aServiceManager) ), + mErrorPtr(aErrorPtr) + { + // nothing else to do + } + + virtual nsresult operator()( const nsIID&, void** ) const; + virtual ~nsGetServiceFromCategory() {}; +protected: + const char* mCategory; + const char* mEntry; + nsCOMPtr mServiceManager; + nsresult* mErrorPtr; +}; + +inline +const nsGetServiceFromCategory +do_GetServiceFromCategory( const char* category, const char* entry, + nsresult* error = 0) + { + return nsGetServiceFromCategory(category, entry, 0, error); + } //////////////////////////////////////////////////////////////////////////////// // NS_WITH_SERVICE: macro to make using services easier. diff --git a/mozilla/xpcom/components/nsServiceManager.cpp b/mozilla/xpcom/components/nsServiceManager.cpp index 3acfaa3a4cb..7f7d0ad22e7 100644 --- a/mozilla/xpcom/components/nsServiceManager.cpp +++ b/mozilla/xpcom/components/nsServiceManager.cpp @@ -22,6 +22,8 @@ */ #include "nsIServiceManager.h" +#include "nsICategoryManager.h" +#include "nsXPIDLString.h" #include "nsVoidArray.h" #include "nsHashtable.h" #include "prcmon.h" @@ -74,6 +76,53 @@ nsGetServiceByProgID::operator()( const nsIID& aIID, void** aInstancePtr ) const return status; } +nsresult +nsGetServiceFromCategory::operator()( const nsIID& aIID, void** aInstancePtr) + const +{ + nsresult status; + nsXPIDLCString value; + nsCOMPtr catman = + do_GetService(NS_CATEGORYMANAGER_PROGID, &status); + + if (NS_FAILED(status)) goto error; + + if (!mCategory || !mEntry) { + // when categories have defaults, use that for null mEntry + status = NS_ERROR_NULL_POINTER; + goto error; + } + + /* find the progID for category.entry */ + status = catman->GetCategoryEntry(mCategory, mEntry, + getter_Copies(value)); + if (NS_FAILED(status)) goto error; + if (!value) { + status = NS_ERROR_SERVICE_NOT_FOUND; + goto error; + } + + // Too bad |nsServiceManager| isn't an |nsIServiceManager|, then + // this could have been one call. + if ( mServiceManager ) + status = + mServiceManager->GetService(value, aIID, + NS_REINTERPRET_CAST(nsISupports**, + aInstancePtr), 0); + else + status = + nsServiceManager::GetService(value, aIID, + NS_REINTERPRET_CAST(nsISupports**, + aInstancePtr), 0); + if (NS_FAILED(status)) { + error: + *aInstancePtr = 0; + } + + *mErrorPtr = status; + return status; +} + class nsServiceEntry { public: