Bug 1409249: Require singleton constructors to return explicit already_AddRefed. r?froydnj
Right now, NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR expects singleton
constructors to return already-addrefed raw pointers, and while it accepts
constructors that return already_AddRefed, most existing don't do so.
Meanwhile, the convention elsewhere is that a raw pointer return value is
owned by the callee, and that the caller needs to addref it if it wants to
keep its own reference to it.
The difference in convention makes it easy to leak (I've definitely caused
more than one shutdown leak this way), so it would be better if we required
the singleton getters to return an explicit already_AddRefed, which would
behave the same for all callers.
This also cleans up several singleton constructors that left a dangling
pointer to their singletons when their initialization methods failed, when
they released their references without clearing their global raw pointers.
MozReview-Commit-ID: 9peyG4pRYcr
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -1494,23 +1494,22 @@ nsScriptSecurityManager::InitStatics()
ClearOnShutdown(&gScriptSecMan);
gScriptSecMan = ssManager;
}
// Currently this nsGenericFactory constructor is used only from FastLoad
// (XPCOM object deserialization) code, when "creating" the system principal
// singleton.
-SystemPrincipal *
+already_AddRefed<SystemPrincipal>
nsScriptSecurityManager::SystemPrincipalSingletonConstructor()
{
- nsIPrincipal *sysprin = nullptr;
if (gScriptSecMan)
- NS_ADDREF(sysprin = gScriptSecMan->mSystemPrincipal);
- return static_cast<SystemPrincipal*>(sysprin);
+ return do_AddRef(gScriptSecMan->mSystemPrincipal.get()).downcast<SystemPrincipal>();
+ return nullptr;
}
struct IsWhitespace {
static bool Test(char aChar) { return NS_IsAsciiWhitespace(aChar); };
};
struct IsWhitespaceOrComma {
static bool Test(char aChar) { return aChar == ',' || NS_IsAsciiWhitespace(aChar); };
};
--- a/caps/nsScriptSecurityManager.h
+++ b/caps/nsScriptSecurityManager.h
@@ -48,17 +48,17 @@ public:
NS_DECL_NSIOBSERVER
static nsScriptSecurityManager*
GetScriptSecurityManager();
// Invoked exactly once, by XPConnect.
static void InitStatics();
- static SystemPrincipal*
+ static already_AddRefed<SystemPrincipal>
SystemPrincipalSingletonConstructor();
/**
* Utility method for comparing two URIs. For security purposes, two URIs
* are equivalent if their schemes, hosts, and ports (if any) match. This
* method returns true if aSubjectURI and aObjectURI have the same origin,
* false otherwise.
*/
--- a/dom/base/DOMRequest.h
+++ b/dom/base/DOMRequest.h
@@ -98,22 +98,20 @@ protected:
class DOMRequestService final : public nsIDOMRequestService
{
~DOMRequestService() {}
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMREQUESTSERVICE
- // Returns an owning reference! No one should call this but the factory.
- static DOMRequestService* FactoryCreate()
+ // No one should call this but the factory.
+ static already_AddRefed<DOMRequestService> FactoryCreate()
{
- DOMRequestService* res = new DOMRequestService;
- NS_ADDREF(res);
- return res;
+ return MakeAndAddRef<DOMRequestService>();
}
};
} // namespace dom
} // namespace mozilla
#define DOMREQUEST_SERVICE_CONTRACTID "@mozilla.org/dom/dom-request-service;1"
--- a/dom/quota/QuotaManagerService.cpp
+++ b/dom/quota/QuotaManagerService.cpp
@@ -243,24 +243,21 @@ QuotaManagerService::GetOrCreate()
QuotaManagerService*
QuotaManagerService::Get()
{
// Does not return an owning reference.
return gQuotaManagerService;
}
// static
-QuotaManagerService*
+already_AddRefed<QuotaManagerService>
QuotaManagerService::FactoryCreate()
{
- // Returns a raw pointer that carries an owning reference! Lame, but the
- // singleton factory macros force this.
- QuotaManagerService* quotaManagerService = GetOrCreate();
- NS_IF_ADDREF(quotaManagerService);
- return quotaManagerService;
+ RefPtr<QuotaManagerService> quotaManagerService = GetOrCreate();
+ return quotaManagerService.forget();
}
void
QuotaManagerService::ClearBackgroundActor()
{
MOZ_ASSERT(NS_IsMainThread());
mBackgroundActor = nullptr;
--- a/dom/quota/QuotaManagerService.h
+++ b/dom/quota/QuotaManagerService.h
@@ -60,18 +60,18 @@ public:
// Returns a non-owning reference.
static QuotaManagerService*
GetOrCreate();
// Returns a non-owning reference.
static QuotaManagerService*
Get();
- // Returns an owning reference! No one should call this but the factory.
- static QuotaManagerService*
+ // No one should call this but the factory.
+ static already_AddRefed<QuotaManagerService>
FactoryCreate();
void
ClearBackgroundActor();
void
NoteLiveManager(QuotaManager* aManager);
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -896,39 +896,36 @@ nsPermissionManager::~nsPermissionManage
}
mPermissionKeyPromiseMap.Clear();
RemoveAllFromMemory();
gPermissionManager = nullptr;
}
// static
-nsIPermissionManager*
+already_AddRefed<nsIPermissionManager>
nsPermissionManager::GetXPCOMSingleton()
{
if (gPermissionManager) {
- NS_ADDREF(gPermissionManager);
- return gPermissionManager;
+ return do_AddRef(gPermissionManager);
}
// Create a new singleton nsPermissionManager.
// We AddRef only once since XPCOM has rules about the ordering of module
// teardowns - by the time our module destructor is called, it's too late to
// Release our members, since GC cycles have already been completed and
// would result in serious leaks.
// See bug 209571.
- gPermissionManager = new nsPermissionManager();
- if (gPermissionManager) {
- NS_ADDREF(gPermissionManager);
- if (NS_FAILED(gPermissionManager->Init())) {
- NS_RELEASE(gPermissionManager);
- }
+ auto permManager = MakeRefPtr<nsPermissionManager>();
+ if (permManager && NS_SUCCEEDED(permManager->Init())) {
+ gPermissionManager = permManager.get();
+ return permManager.forget();
}
- return gPermissionManager;
+ return nullptr;;
}
nsresult
nsPermissionManager::Init()
{
// If the 'permissions.memory_only' pref is set to true, then don't write any
// permission settings to disk, but keep them in a memory-only database.
mMemoryOnlyDB = mozilla::Preferences::GetBool("permissions.memory_only", false);
--- a/extensions/cookie/nsPermissionManager.h
+++ b/extensions/cookie/nsPermissionManager.h
@@ -161,17 +161,17 @@ public:
};
// nsISupports
NS_DECL_ISUPPORTS
NS_DECL_NSIPERMISSIONMANAGER
NS_DECL_NSIOBSERVER
nsPermissionManager();
- static nsIPermissionManager* GetXPCOMSingleton();
+ static already_AddRefed<nsIPermissionManager> GetXPCOMSingleton();
nsresult Init();
// enums for AddInternal()
enum OperationType {
eOperationNone,
eOperationAdding,
eOperationRemoving,
eOperationChanging,
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -136,22 +136,20 @@ nsXPConnect::InitStatics()
MOZ_CRASH("InitSelfHostedCode failed");
if (!gSelf->mRuntime->InitializeStrings(cx))
MOZ_CRASH("InitializeStrings failed");
// Initialize our singleton scopes.
gSelf->mRuntime->InitSingletonScopes();
}
-nsXPConnect*
+already_AddRefed<nsXPConnect>
nsXPConnect::GetSingleton()
{
- nsXPConnect* xpc = nsXPConnect::XPConnect();
- NS_IF_ADDREF(xpc);
- return xpc;
+ return do_AddRef(nsXPConnect::XPConnect());
}
// static
void
nsXPConnect::ReleaseXPConnectSingleton()
{
nsXPConnect* xpc = gSelf;
if (xpc) {
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -258,20 +258,17 @@ public:
static nsIPrincipal* SystemPrincipal()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(gSystemPrincipal);
return gSystemPrincipal;
}
- // This returns an AddRef'd pointer. It does not do this with an 'out' param
- // only because this form is required by the generic module macro:
- // NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR
- static nsXPConnect* GetSingleton();
+ static already_AddRefed<nsXPConnect> GetSingleton();
// Called by module code in dll startup
static void InitStatics();
// Called by module code on dll shutdown.
static void ReleaseXPConnectSingleton();
bool IsShuttingDown() const {return mShuttingDown;}
--- a/modules/libjar/nsJARProtocolHandler.cpp
+++ b/modules/libjar/nsJARProtocolHandler.cpp
@@ -58,33 +58,29 @@ nsJARProtocolHandler::MimeService()
return mMimeService.get();
}
NS_IMPL_ISUPPORTS(nsJARProtocolHandler,
nsIJARProtocolHandler,
nsIProtocolHandler,
nsISupportsWeakReference)
-nsJARProtocolHandler*
+already_AddRefed<nsJARProtocolHandler>
nsJARProtocolHandler::GetSingleton()
{
if (!gJarHandler) {
- gJarHandler = new nsJARProtocolHandler();
- if (!gJarHandler)
- return nullptr;
-
- NS_ADDREF(gJarHandler);
- nsresult rv = gJarHandler->Init();
- if (NS_FAILED(rv)) {
- NS_RELEASE(gJarHandler);
+ auto jar = MakeRefPtr<nsJARProtocolHandler>();
+ gJarHandler = jar.get();
+ if (!jar || NS_FAILED(jar->Init())) {
+ gJarHandler = nullptr;
return nullptr;
}
+ return jar.forget();
}
- NS_ADDREF(gJarHandler);
- return gJarHandler;
+ return do_AddRef(gJarHandler);
}
NS_IMETHODIMP
nsJARProtocolHandler::GetJARCache(nsIZipReaderCache* *result)
{
*result = mJARCache;
NS_ADDREF(*result);
return NS_OK;
--- a/modules/libjar/nsJARProtocolHandler.h
+++ b/modules/libjar/nsJARProtocolHandler.h
@@ -20,17 +20,17 @@ class nsJARProtocolHandler final : publi
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIPROTOCOLHANDLER
NS_DECL_NSIJARPROTOCOLHANDLER
// nsJARProtocolHandler methods:
nsJARProtocolHandler();
- static nsJARProtocolHandler *GetSingleton();
+ static already_AddRefed<nsJARProtocolHandler> GetSingleton();
nsresult Init();
// returns non addref'ed pointer.
nsIMIMEService *MimeService();
nsIZipReaderCache *JarCache() { return mJARCache; }
protected:
virtual ~nsJARProtocolHandler();
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -3886,22 +3886,21 @@ public:
NS_IMETHOD Run() override
{
return RegisterStrongMemoryReporter(new PreferenceServiceReporter());
}
};
} // namespace
-/* static */ Preferences*
+/* static */ already_AddRefed<Preferences>
Preferences::GetInstanceForService()
{
if (sPreferences) {
- NS_ADDREF(sPreferences);
- return sPreferences;
+ return do_AddRef(sPreferences);
}
if (sShutdown) {
gCacheDataDesc = "shutting down in GetInstanceForService()";
return nullptr;
}
sRootBranch = new nsPrefBranch("", false);
@@ -3912,34 +3911,34 @@ Preferences::GetInstanceForService()
sPreferences = new Preferences();
NS_ADDREF(sPreferences);
Result<Ok, const char*> res = sPreferences->Init();
if (res.isErr()) {
// The singleton instance will delete sRootBranch and sDefaultRootBranch.
gCacheDataDesc = res.unwrapErr();
NS_RELEASE(sPreferences);
+ sPreferences = nullptr;
return nullptr;
}
gCacheData = new nsTArray<nsAutoPtr<CacheData>>();
gCacheDataDesc = "set by GetInstanceForService()";
gObserverTable = new nsRefPtrHashtable<ValueObserverHashKey, ValueObserver>();
// Preferences::GetInstanceForService() can be called from GetService(), and
// RegisterStrongMemoryReporter calls GetService(nsIMemoryReporter). To
// avoid a potential recursive GetService() call, we can't register the
// memory reporter here; instead, do it off a runnable.
RefPtr<AddPreferencesMemoryReporterRunnable> runnable =
new AddPreferencesMemoryReporterRunnable();
NS_DispatchToMainThread(runnable);
- NS_ADDREF(sPreferences);
- return sPreferences;
+ return do_AddRef(sPreferences);
}
/* static */ bool
Preferences::IsServiceAvailable()
{
return !!sPreferences;
}
--- a/modules/libpref/Preferences.h
+++ b/modules/libpref/Preferences.h
@@ -73,17 +73,17 @@ public:
// Returns true if the Preferences service is available, false otherwise.
static bool IsServiceAvailable();
// Initialize user prefs from prefs.js/user.js
static void InitializeUserPrefs();
// Returns the singleton instance which is addreffed.
- static Preferences* GetInstanceForService();
+ static already_AddRefed<Preferences> GetInstanceForService();
// Finallizes global members.
static void Shutdown();
// Returns shared pref service instance NOTE: not addreffed.
static nsIPrefService* GetService()
{
NS_ENSURE_TRUE(InitStaticMembers(), nullptr);
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -346,33 +346,29 @@ nsIOService::InitializeProtocolProxyServ
if (XRE_IsParentProcess()) {
// for early-initialization
Unused << do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
}
return rv;
}
-nsIOService*
+already_AddRefed<nsIOService>
nsIOService::GetInstance() {
if (!gIOService) {
- gIOService = new nsIOService();
- if (!gIOService)
- return nullptr;
- NS_ADDREF(gIOService);
-
- nsresult rv = gIOService->Init();
- if (NS_FAILED(rv)) {
- NS_RELEASE(gIOService);
+ RefPtr<nsIOService> ios = new nsIOService();
+ gIOService = ios.get();
+ if (!ios || NS_FAILED(ios->Init())) {
+ gIOService = nullptr;
return nullptr;
}
- return gIOService;
+
+ return ios.forget();
}
- NS_ADDREF(gIOService);
- return gIOService;
+ return do_AddRef(gIOService);
}
NS_IMPL_ISUPPORTS(nsIOService,
nsIIOService,
nsIIOService2,
nsINetUtil,
nsISpeculativeConnect,
nsIObserver,
--- a/netwerk/base/nsIOService.h
+++ b/netwerk/base/nsIOService.h
@@ -59,18 +59,17 @@ public:
NS_DECL_NSIIOSERVICE2
NS_DECL_NSIOBSERVER
NS_DECL_NSINETUTIL
NS_DECL_NSISPECULATIVECONNECT
NS_DECL_NSIIOSERVICEINTERNAL
// Gets the singleton instance of the IO Service, creating it as needed
// Returns nullptr on out of memory or failure to initialize.
- // Returns an addrefed pointer.
- static nsIOService* GetInstance();
+ static already_AddRefed<nsIOService> GetInstance();
nsresult Init();
nsresult NewURI(const char* aSpec, nsIURI* aBaseURI,
nsIURI* *result,
nsIProtocolHandler* *hdlrResult);
// Called by channels before a redirect happens. This notifies the global
// redirect observers.
--- a/netwerk/dns/ChildDNSService.cpp
+++ b/netwerk/dns/ChildDNSService.cpp
@@ -21,26 +21,25 @@ namespace net {
//-----------------------------------------------------------------------------
// ChildDNSService
//-----------------------------------------------------------------------------
static ChildDNSService *gChildDNSService;
static const char kPrefNameDisablePrefetch[] = "network.dns.disablePrefetch";
-ChildDNSService* ChildDNSService::GetSingleton()
+already_AddRefed<ChildDNSService> ChildDNSService::GetSingleton()
{
MOZ_ASSERT(IsNeckoChild());
if (!gChildDNSService) {
gChildDNSService = new ChildDNSService();
}
- NS_ADDREF(gChildDNSService);
- return gChildDNSService;
+ return do_AddRef(gChildDNSService);
}
NS_IMPL_ISUPPORTS(ChildDNSService,
nsIDNSService,
nsPIDNSService,
nsIObserver)
ChildDNSService::ChildDNSService()
--- a/netwerk/dns/ChildDNSService.h
+++ b/netwerk/dns/ChildDNSService.h
@@ -27,17 +27,17 @@ public:
// AsyncResolve (and CancelAsyncResolve) can be called off-main
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSPIDNSSERVICE
NS_DECL_NSIDNSSERVICE
NS_DECL_NSIOBSERVER
ChildDNSService();
- static ChildDNSService* GetSingleton();
+ static already_AddRefed<ChildDNSService> GetSingleton();
void NotifyRequestDone(DNSRequestChild *aDnsRequest);
bool GetOffline() const;
private:
virtual ~ChildDNSService();
void MOZ_ALWAYS_INLINE GetDNSRecordHashKey(const nsACString &aHost,
--- a/netwerk/dns/nsDNSService2.cpp
+++ b/netwerk/dns/nsDNSService2.cpp
@@ -494,45 +494,43 @@ NS_IMPL_ISUPPORTS(nsDNSService, nsIDNSSe
nsIMemoryReporter)
/******************************************************************************
* nsDNSService impl:
* singleton instance ctor/dtor methods
******************************************************************************/
static nsDNSService *gDNSService;
-nsIDNSService*
+already_AddRefed<nsIDNSService>
nsDNSService::GetXPCOMSingleton()
{
if (IsNeckoChild()) {
return ChildDNSService::GetSingleton();
}
return GetSingleton();
}
-nsDNSService*
+already_AddRefed<nsDNSService>
nsDNSService::GetSingleton()
{
NS_ASSERTION(!IsNeckoChild(), "not a parent process");
if (gDNSService) {
- NS_ADDREF(gDNSService);
- return gDNSService;
+ return do_AddRef(gDNSService);
}
- gDNSService = new nsDNSService();
- if (gDNSService) {
- NS_ADDREF(gDNSService);
- if (NS_FAILED(gDNSService->Init())) {
- NS_RELEASE(gDNSService);
- }
+ auto dns = MakeRefPtr<nsDNSService>();
+ gDNSService = dns.get();
+ if (!dns || NS_FAILED(dns->Init())) {
+ gDNSService = nullptr;
+ return nullptr;
}
- return gDNSService;
+ return dns.forget();
}
NS_IMETHODIMP
nsDNSService::Init()
{
if (mResolver)
return NS_OK;
NS_ENSURE_TRUE(!mResolver, NS_ERROR_ALREADY_INITIALIZED);
--- a/netwerk/dns/nsDNSService2.h
+++ b/netwerk/dns/nsDNSService2.h
@@ -29,34 +29,34 @@ public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSPIDNSSERVICE
NS_DECL_NSIDNSSERVICE
NS_DECL_NSIOBSERVER
NS_DECL_NSIMEMORYREPORTER
nsDNSService();
- static nsIDNSService* GetXPCOMSingleton();
+ static already_AddRefed<nsIDNSService> GetXPCOMSingleton();
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
bool GetOffline() const;
protected:
friend class nsAuthSSPI;
nsresult DeprecatedSyncResolve(const nsACString &aHostname,
uint32_t flags,
const mozilla::OriginAttributes &aOriginAttributes,
nsIDNSRecord **result);
private:
~nsDNSService();
- static nsDNSService* GetSingleton();
+ static already_AddRefed<nsDNSService> GetSingleton();
uint16_t GetAFForLookup(const nsACString &host, uint32_t flags);
nsresult PreprocessHostname(bool aLocalDomain,
const nsACString &aInput,
nsIIDNService *aIDN,
nsACString &aACE);
--- a/startupcache/StartupCache.cpp
+++ b/startupcache/StartupCache.cpp
@@ -695,23 +695,22 @@ StartupCacheDebugOutputStream::PutBuffer
mBinaryStream->PutBuffer(aBuffer, aLength);
}
#endif //DEBUG
StartupCacheWrapper* StartupCacheWrapper::gStartupCacheWrapper = nullptr;
NS_IMPL_ISUPPORTS(StartupCacheWrapper, nsIStartupCache)
-StartupCacheWrapper* StartupCacheWrapper::GetSingleton()
+already_AddRefed<StartupCacheWrapper> StartupCacheWrapper::GetSingleton()
{
if (!gStartupCacheWrapper)
gStartupCacheWrapper = new StartupCacheWrapper();
- NS_ADDREF(gStartupCacheWrapper);
- return gStartupCacheWrapper;
+ return do_AddRef(gStartupCacheWrapper);
}
nsresult
StartupCacheWrapper::GetBuffer(const char* id, char** outbuf, uint32_t* length)
{
StartupCache* sc = StartupCache::GetSingleton();
if (!sc) {
return NS_ERROR_NOT_INITIALIZED;
--- a/startupcache/StartupCache.h
+++ b/startupcache/StartupCache.h
@@ -209,16 +209,16 @@ class StartupCacheDebugOutputStream fina
class StartupCacheWrapper final
: public nsIStartupCache
{
~StartupCacheWrapper() {}
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISTARTUPCACHE
- static StartupCacheWrapper* GetSingleton();
+ static already_AddRefed<StartupCacheWrapper> GetSingleton();
static StartupCacheWrapper *gStartupCacheWrapper;
};
} // namespace scache
} // namespace mozilla
#endif //StartupCache_h_
--- a/storage/VacuumManager.cpp
+++ b/storage/VacuumManager.cpp
@@ -306,33 +306,28 @@ Vacuumer::notifyCompletion(bool aSucceed
NS_IMPL_ISUPPORTS(
VacuumManager
, nsIObserver
)
VacuumManager *
VacuumManager::gVacuumManager = nullptr;
-VacuumManager *
+already_AddRefed<VacuumManager>
VacuumManager::getSingleton()
{
//Don't allocate it in the child Process.
if (!XRE_IsParentProcess()) {
return nullptr;
}
- if (gVacuumManager) {
- NS_ADDREF(gVacuumManager);
- return gVacuumManager;
+ if (!gVacuumManager) {
+ gVacuumManager = new VacuumManager();
}
- gVacuumManager = new VacuumManager();
- if (gVacuumManager) {
- NS_ADDREF(gVacuumManager);
- }
- return gVacuumManager;
+ return do_AddRef(gVacuumManager);
}
VacuumManager::VacuumManager()
: mParticipants("vacuum-participant")
{
MOZ_ASSERT(!gVacuumManager,
"Attempting to create two instances of the service!");
gVacuumManager = this;
--- a/storage/VacuumManager.h
+++ b/storage/VacuumManager.h
@@ -23,17 +23,17 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
VacuumManager();
/**
* Obtains the VacuumManager object.
*/
- static VacuumManager * getSingleton();
+ static already_AddRefed<VacuumManager> getSingleton();
private:
~VacuumManager();
static VacuumManager *gVacuumManager;
// Cache of components registered in "vacuum-participant" category.
nsCategoryCache<mozIStorageVacuumParticipant> mParticipants;
--- a/storage/mozStorageService.cpp
+++ b/storage/mozStorageService.cpp
@@ -184,22 +184,21 @@ NS_IMPL_ISUPPORTS(
Service,
mozIStorageService,
nsIObserver,
nsIMemoryReporter
)
Service *Service::gService = nullptr;
-Service *
+already_AddRefed<Service>
Service::getSingleton()
{
if (gService) {
- NS_ADDREF(gService);
- return gService;
+ return do_AddRef(gService);
}
// Ensure that we are using the same version of SQLite that we compiled with
// or newer. Our configure check ensures we are using a new enough version
// at compile time.
if (SQLITE_VERSION_NUMBER > ::sqlite3_libversion_number()) {
nsCOMPtr<nsIPromptService> ps(do_GetService(NS_PROMPTSERVICE_CONTRACTID));
if (ps) {
@@ -213,24 +212,24 @@ Service::getSingleton()
(void)ps->Alert(nullptr, title.get(), message.get());
}
MOZ_CRASH("SQLite Version Error");
}
// The first reference to the storage service must be obtained on the
// main thread.
NS_ENSURE_TRUE(NS_IsMainThread(), nullptr);
- gService = new Service();
- if (gService) {
- NS_ADDREF(gService);
- if (NS_FAILED(gService->initialize()))
- NS_RELEASE(gService);
+ RefPtr<Service> service = new Service();
+ gService = service.get();
+ if (!service || NS_FAILED(service->initialize())) {
+ gService = nullptr;
+ return nullptr;
}
- return gService;
+ return service.forget();
}
nsIXPConnect *Service::sXPConnect = nullptr;
// static
already_AddRefed<nsIXPConnect>
Service::getXPConnect()
{
--- a/storage/mozStorageService.h
+++ b/storage/mozStorageService.h
@@ -47,17 +47,17 @@ public:
* @return aStr1 - aStr2. That is, if aStr1 < aStr2, returns a negative
* number. If aStr1 > aStr2, returns a positive number. If
* aStr1 == aStr2, returns 0.
*/
int localeCompareStrings(const nsAString &aStr1,
const nsAString &aStr2,
int32_t aComparisonStrength);
- static Service *getSingleton();
+ static already_AddRefed<Service> getSingleton();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_MOZISTORAGESERVICE
NS_DECL_NSIOBSERVER
NS_DECL_NSIMEMORYREPORTER
/**
* Obtains an already AddRefed pointer to XPConnect. This is used by
--- a/toolkit/components/downloads/ApplicationReputation.cpp
+++ b/toolkit/components/downloads/ApplicationReputation.cpp
@@ -1547,31 +1547,23 @@ PendingLookup::OnStopRequestInternal(nsI
}
NS_IMPL_ISUPPORTS(ApplicationReputationService,
nsIApplicationReputationService)
ApplicationReputationService*
ApplicationReputationService::gApplicationReputationService = nullptr;
-ApplicationReputationService*
+already_AddRefed<ApplicationReputationService>
ApplicationReputationService::GetSingleton()
{
- if (gApplicationReputationService) {
- NS_ADDREF(gApplicationReputationService);
- return gApplicationReputationService;
+ if (!gApplicationReputationService) {
+ gApplicationReputationService = new ApplicationReputationService();
}
-
- // We're not initialized yet.
- gApplicationReputationService = new ApplicationReputationService();
- if (gApplicationReputationService) {
- NS_ADDREF(gApplicationReputationService);
- }
-
- return gApplicationReputationService;
+ return do_AddRef(gApplicationReputationService);
}
ApplicationReputationService::ApplicationReputationService()
{
LOG(("Application reputation service started up"));
}
ApplicationReputationService::~ApplicationReputationService() {
--- a/toolkit/components/downloads/ApplicationReputation.h
+++ b/toolkit/components/downloads/ApplicationReputation.h
@@ -22,17 +22,17 @@ class PendingLookup;
class ApplicationReputationService final :
public nsIApplicationReputationService {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIAPPLICATIONREPUTATIONSERVICE
public:
- static ApplicationReputationService* GetSingleton();
+ static already_AddRefed<ApplicationReputationService> GetSingleton();
private:
friend class PendingLookup;
friend class PendingDBLookup;
/**
* Global singleton object for holding this factory service.
*/
static ApplicationReputationService* gApplicationReputationService;
--- a/toolkit/components/downloads/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/nsDownloadManager.cpp
@@ -20,32 +20,30 @@ using namespace mozilla;
NS_IMPL_ISUPPORTS(
nsDownloadManager
, nsIDownloadManager
)
nsDownloadManager *nsDownloadManager::gDownloadManagerService = nullptr;
-nsDownloadManager *
+already_AddRefed<nsDownloadManager>
nsDownloadManager::GetSingleton()
{
if (gDownloadManagerService) {
- NS_ADDREF(gDownloadManagerService);
- return gDownloadManagerService;
+ return do_AddRef(gDownloadManagerService);
}
- gDownloadManagerService = new nsDownloadManager();
- if (gDownloadManagerService) {
- NS_ADDREF(gDownloadManagerService);
- if (NS_FAILED(gDownloadManagerService->Init()))
- NS_RELEASE(gDownloadManagerService);
+ auto serv = MakeRefPtr<nsDownloadManager>();
+ gDownloadManagerService = serv.get();
+ if (!serv || NS_FAILED(serv->Init())) {
+ gDownloadManagerService = serv.get();
+ return nullptr;
}
-
- return gDownloadManagerService;
+ return serv.forget();
}
nsDownloadManager::~nsDownloadManager()
{
gDownloadManagerService = nullptr;
}
nsresult
--- a/toolkit/components/downloads/nsDownloadManager.h
+++ b/toolkit/components/downloads/nsDownloadManager.h
@@ -16,17 +16,17 @@
class nsDownloadManager final : public nsIDownloadManager
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOWNLOADMANAGER
nsresult Init();
- static nsDownloadManager *GetSingleton();
+ static already_AddRefed<nsDownloadManager> GetSingleton();
nsDownloadManager()
{
}
protected:
virtual ~nsDownloadManager();
--- a/toolkit/components/places/History.cpp
+++ b/toolkit/components/places/History.cpp
@@ -2416,27 +2416,26 @@ History::GetService()
if (service) {
NS_ASSERTION(gService, "Our constructor was not run?!");
}
return gService;
}
/* static */
-History*
+already_AddRefed<History>
History::GetSingleton()
{
if (!gService) {
gService = new History();
NS_ENSURE_TRUE(gService, nullptr);
gService->InitMemoryReporter();
}
- NS_ADDREF(gService);
- return gService;
+ return do_AddRef(gService);
}
mozIStorageConnection*
History::GetDBConn()
{
MOZ_ASSERT(NS_IsMainThread());
if (mShuttingDown)
return nullptr;
--- a/toolkit/components/places/History.h
+++ b/toolkit/components/places/History.h
@@ -102,20 +102,19 @@ public:
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
/**
* Obtains a pointer to this service.
*/
static History* GetService();
/**
- * Obtains a pointer that has had AddRef called on it. Used by the service
- * manager only.
+ * Used by the service manager only.
*/
- static History* GetSingleton();
+ static already_AddRefed<History> GetSingleton();
template<int N>
already_AddRefed<mozIStorageStatement>
GetStatement(const char (&aQuery)[N])
{
// May be invoked on both threads.
const mozIStorageConnection* dbConn = GetConstDBConn();
NS_ENSURE_TRUE(dbConn, nullptr);
--- a/toolkit/mozapps/extensions/AddonPathService.cpp
+++ b/toolkit/mozapps/extensions/AddonPathService.cpp
@@ -52,24 +52,23 @@ AddonPathService::~AddonPathService()
{
sInstance = nullptr;
}
NS_IMPL_ISUPPORTS(AddonPathService, amIAddonPathService)
AddonPathService *AddonPathService::sInstance;
-/* static */ AddonPathService*
+/* static */ already_AddRefed<AddonPathService>
AddonPathService::GetInstance()
{
if (!sInstance) {
sInstance = new AddonPathService();
}
- NS_ADDREF(sInstance);
- return sInstance;
+ return do_AddRef(sInstance);
}
static JSAddonId*
ConvertAddonId(const nsAString& addonIdString)
{
AutoSafeJSContext cx;
JS::RootedValue strv(cx);
if (!mozilla::dom::ToJSValue(cx, addonIdString, &strv)) {
--- a/toolkit/mozapps/extensions/AddonPathService.h
+++ b/toolkit/mozapps/extensions/AddonPathService.h
@@ -18,17 +18,17 @@ namespace mozilla {
JSAddonId*
MapURIToAddonID(nsIURI* aURI);
class AddonPathService final : public amIAddonPathService
{
public:
AddonPathService();
- static AddonPathService* GetInstance();
+ static already_AddRefed<AddonPathService> GetInstance();
JSAddonId* Find(const nsAString& path);
static JSAddonId* FindAddonId(const nsAString& path);
NS_DECL_ISUPPORTS
NS_DECL_AMIADDONPATHSERVICE
struct PathEntry
--- a/uriloader/prefetch/nsOfflineCacheUpdate.h
+++ b/uriloader/prefetch/nsOfflineCacheUpdate.h
@@ -351,18 +351,17 @@ public:
virtual nsresult UpdateFinished(nsOfflineCacheUpdate *aUpdate) override;
/**
* Returns the singleton nsOfflineCacheUpdateService without an addref, or
* nullptr if the service couldn't be created.
*/
static nsOfflineCacheUpdateService *EnsureService();
- /** Addrefs and returns the singleton nsOfflineCacheUpdateService. */
- static nsOfflineCacheUpdateService *GetInstance();
+ static already_AddRefed<nsOfflineCacheUpdateService> GetInstance();
static nsresult OfflineAppPinnedForURI(nsIURI *aDocumentURI,
nsIPrefBranch *aPrefBranch,
bool *aPinned);
static nsTHashtable<nsCStringHashKey>* AllowedDomains();
private:
--- a/uriloader/prefetch/nsOfflineCacheUpdateService.cpp
+++ b/uriloader/prefetch/nsOfflineCacheUpdateService.cpp
@@ -287,35 +287,30 @@ nsOfflineCacheUpdateService::Init()
NS_ENSURE_SUCCESS(rv, rv);
gOfflineCacheUpdateService = this;
return NS_OK;
}
/* static */
-nsOfflineCacheUpdateService *
+already_AddRefed<nsOfflineCacheUpdateService>
nsOfflineCacheUpdateService::GetInstance()
{
if (!gOfflineCacheUpdateService) {
- gOfflineCacheUpdateService = new nsOfflineCacheUpdateService();
- if (!gOfflineCacheUpdateService)
- return nullptr;
- NS_ADDREF(gOfflineCacheUpdateService);
- nsresult rv = gOfflineCacheUpdateService->Init();
- if (NS_FAILED(rv)) {
- NS_RELEASE(gOfflineCacheUpdateService);
+ auto serv = MakeRefPtr<nsOfflineCacheUpdateService>();
+ gOfflineCacheUpdateService = serv.get();
+ if (!serv || NS_FAILED(serv->Init())) {
+ gOfflineCacheUpdateService = nullptr;
return nullptr;
}
- return gOfflineCacheUpdateService;
+ return serv.forget();
}
- NS_ADDREF(gOfflineCacheUpdateService);
-
- return gOfflineCacheUpdateService;
+ return do_AddRef(gOfflineCacheUpdateService);
}
/* static */
nsOfflineCacheUpdateService *
nsOfflineCacheUpdateService::EnsureService()
{
if (!gOfflineCacheUpdateService) {
// Make the service manager hold a long-lived reference to the service
--- a/xpcom/components/ModuleUtils.h
+++ b/xpcom/components/ModuleUtils.h
@@ -44,30 +44,52 @@ static nsresult
rv = inst->_InitMethod(); \
if (NS_SUCCEEDED(rv)) { \
rv = inst->QueryInterface(aIID, aResult); \
} \
\
return rv; \
}
+namespace mozilla {
+namespace detail {
+
+template<typename T>
+struct RemoveAlreadyAddRefed
+{
+ using Type = T;
+};
+
+template<typename T>
+struct RemoveAlreadyAddRefed<already_AddRefed<T>>
+{
+ using Type = T;
+};
+
+} // namespace detail
+} // namespace mozilla
+
// 'Constructor' that uses an existing getter function that gets a singleton.
-// NOTE: assumes that getter does an AddRef - so additional AddRef is not done.
#define NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(_InstanceClass, _GetterProc) \
static nsresult \
_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
void **aResult) \
{ \
RefPtr<_InstanceClass> inst; \
\
*aResult = nullptr; \
if (nullptr != aOuter) { \
return NS_ERROR_NO_AGGREGATION; \
} \
\
- inst = already_AddRefed<_InstanceClass>(_GetterProc()); \
+ using T = mozilla::detail::RemoveAlreadyAddRefed<decltype(_GetterProc())>::Type; \
+ static_assert(mozilla::IsSame<already_AddRefed<T>, decltype(_GetterProc())>::value, \
+ "Singleton constructor must return already_AddRefed"); \
+ static_assert(mozilla::IsBaseOf<_InstanceClass, T>::value, \
+ "Singleton constructor must return correct already_AddRefed"); \
+ inst = _GetterProc(); \
if (nullptr == inst) { \
return NS_ERROR_OUT_OF_MEMORY; \
} \
return inst->QueryInterface(aIID, aResult); \
}
#endif // mozilla_GenericModule_h