/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/mailnews/Services.h" #include "nsIObserverService.h" #include "nsIObserver.h" #include "nsServiceManagerUtils.h" // All of the includes for the services we initiate here #include "mozINewMailNotificationService.h" #include "nsIAbManager.h" #include "nsIImapService.h" #include "nsIImportService.h" #include "nsIMimeConverter.h" #include "nsIMsgAccountManager.h" #include "nsIMsgComposeService.h" #include "nsIMsgCopyService.h" #include "nsIMsgDatabase.h" #include "nsIMsgFilterService.h" #include "nsIMsgFolderNotificationService.h" #include "nsIMsgHeaderParser.h" #include "nsIMsgMailSession.h" #include "nsIMsgTagService.h" #include "nsINntpService.h" #include "nsIPop3Service.h" #include "nsISmtpService.h" namespace mozilla { namespace services { namespace { class ShutdownObserver final : public nsIObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER static void EnsureInitialized(); private: ~ShutdownObserver() {} void ShutdownServices(); static ShutdownObserver *sShutdownObserver; static bool sShuttingDown; }; bool ShutdownObserver::sShuttingDown = false; ShutdownObserver *ShutdownObserver::sShutdownObserver = nullptr; } #define MOZ_SERVICE(NAME, TYPE, CONTRACT_ID) \ static TYPE *g##NAME = nullptr; \ already_AddRefed Get##NAME() \ { \ ShutdownObserver::EnsureInitialized(); \ if (!g##NAME) \ { \ nsCOMPtr os = do_GetService(CONTRACT_ID); \ os.forget(&g##NAME); \ MOZ_ASSERT(g##NAME, "This service is unexpectedly missing."); \ } \ nsCOMPtr ret = g##NAME; \ return ret.forget(); \ } #include "mozilla/mailnews/ServiceList.h" #undef MOZ_SERVICE NS_IMPL_ISUPPORTS(ShutdownObserver, nsIObserver) NS_IMETHODIMP ShutdownObserver::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData) { if (!strcmp(aTopic, "xpcom-shutdown-threads")) ShutdownServices(); return NS_OK; } void ShutdownObserver::EnsureInitialized() { MOZ_ASSERT(!sShuttingDown, "It is illegal to use this code after shutdown!"); if (!sShutdownObserver) { sShutdownObserver = new ShutdownObserver; sShutdownObserver->AddRef(); nsCOMPtr obs(mozilla::services::GetObserverService()); MOZ_ASSERT(obs, "This should never be null"); obs->AddObserver(sShutdownObserver, "xpcom-shutdown-threads", false); } } void ShutdownObserver::ShutdownServices() { sShuttingDown = true; MOZ_ASSERT(sShutdownObserver, "Shutting down twice?"); sShutdownObserver->Release(); sShutdownObserver = nullptr; #define MOZ_SERVICE(NAME, TYPE, CONTRACT_ID) NS_IF_RELEASE(g##NAME); #include "mozilla/mailnews/ServiceList.h" #undef MOZ_SERVICE } } // namespace services } // namespace mozilla