diff options
Diffstat (limited to 'xpcom/components/nsComponentManager.h')
-rw-r--r-- | xpcom/components/nsComponentManager.h | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/xpcom/components/nsComponentManager.h b/xpcom/components/nsComponentManager.h new file mode 100644 index 000000000..f0e0f684a --- /dev/null +++ b/xpcom/components/nsComponentManager.h @@ -0,0 +1,363 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef nsComponentManager_h__ +#define nsComponentManager_h__ + +#include "nsXPCOM.h" + +#include "xpcom-private.h" +#include "nsIComponentManager.h" +#include "nsIComponentRegistrar.h" +#include "nsIMemoryReporter.h" +#include "nsIServiceManager.h" +#include "nsIFile.h" +#include "mozilla/Atomics.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/Module.h" +#include "mozilla/ModuleLoader.h" +#include "mozilla/Mutex.h" +#include "nsXULAppAPI.h" +#include "nsNativeModuleLoader.h" +#include "nsIFactory.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "PLDHashTable.h" +#include "prtime.h" +#include "nsCOMPtr.h" +#include "nsAutoPtr.h" +#include "nsWeakReference.h" +#include "plarena.h" +#include "nsCOMArray.h" +#include "nsDataHashtable.h" +#include "nsInterfaceHashtable.h" +#include "nsClassHashtable.h" +#include "nsTArray.h" + +#include "mozilla/Omnijar.h" +#include "mozilla/Attributes.h" + +struct nsFactoryEntry; +class nsIServiceManager; +struct PRThread; + +#define NS_COMPONENTMANAGER_CID \ +{ /* 91775d60-d5dc-11d2-92fb-00e09805570f */ \ + 0x91775d60, \ + 0xd5dc, \ + 0x11d2, \ + {0x92, 0xfb, 0x00, 0xe0, 0x98, 0x05, 0x57, 0x0f} \ +} + +/* keys for registry use */ +extern const char xpcomKeyName[]; +extern const char xpcomComponentsKeyName[]; +extern const char lastModValueName[]; +extern const char fileSizeValueName[]; +extern const char nativeComponentType[]; +extern const char staticComponentType[]; + +#ifdef DEBUG +#define XPCOM_CHECK_PENDING_CIDS +#endif +//////////////////////////////////////////////////////////////////////////////// + +extern const mozilla::Module kXPCOMModule; + +/** + * This is a wrapper around mozilla::Mutex which provides runtime + * checking for a deadlock where the same thread tries to lock a mutex while + * it is already locked. This checking is present in both debug and release + * builds. + */ +class SafeMutex +{ +public: + explicit SafeMutex(const char* aName) + : mMutex(aName) + , mOwnerThread(nullptr) + { + } + + ~SafeMutex() {} + + void Lock() + { + AssertNotCurrentThreadOwns(); + mMutex.Lock(); + MOZ_ASSERT(mOwnerThread == nullptr); + mOwnerThread = PR_GetCurrentThread(); + } + + void Unlock() + { + MOZ_ASSERT(mOwnerThread == PR_GetCurrentThread()); + mOwnerThread = nullptr; + mMutex.Unlock(); + } + + void AssertCurrentThreadOwns() const + { + // This method is a debug-only check + MOZ_ASSERT(mOwnerThread == PR_GetCurrentThread()); + } + + MOZ_NEVER_INLINE void AssertNotCurrentThreadOwns() const + { + // This method is a release-mode check + if (PR_GetCurrentThread() == mOwnerThread) { + MOZ_CRASH(); + } + } + +private: + mozilla::Mutex mMutex; + mozilla::Atomic<PRThread*, mozilla::Relaxed> mOwnerThread; +}; + +typedef mozilla::BaseAutoLock<SafeMutex> SafeMutexAutoLock; +typedef mozilla::BaseAutoUnlock<SafeMutex> SafeMutexAutoUnlock; + +class nsComponentManagerImpl final + : public nsIComponentManager + , public nsIServiceManager + , public nsSupportsWeakReference + , public nsIComponentRegistrar + , public nsIInterfaceRequestor + , public nsIMemoryReporter +{ +public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIINTERFACEREQUESTOR + NS_DECL_NSICOMPONENTMANAGER + NS_DECL_NSICOMPONENTREGISTRAR + NS_DECL_NSIMEMORYREPORTER + + static nsresult Create(nsISupports* aOuter, REFNSIID aIID, void** aResult); + + nsresult RegistryLocationForFile(nsIFile* aFile, + nsCString& aResult); + nsresult FileForRegistryLocation(const nsCString& aLocation, + nsIFile** aSpec); + + NS_DECL_NSISERVICEMANAGER + + // nsComponentManagerImpl methods: + nsComponentManagerImpl(); + + static nsComponentManagerImpl* gComponentManager; + nsresult Init(); + + nsresult Shutdown(void); + + nsresult FreeServices(); + + already_AddRefed<mozilla::ModuleLoader> LoaderForExtension(const nsACString& aExt); + nsInterfaceHashtable<nsCStringHashKey, mozilla::ModuleLoader> mLoaderMap; + + already_AddRefed<nsIFactory> FindFactory(const nsCID& aClass); + already_AddRefed<nsIFactory> FindFactory(const char* aContractID, + uint32_t aContractIDLen); + + already_AddRefed<nsIFactory> LoadFactory(nsFactoryEntry* aEntry); + + nsFactoryEntry* GetFactoryEntry(const char* aContractID, + uint32_t aContractIDLen); + nsFactoryEntry* GetFactoryEntry(const nsCID& aClass); + + nsDataHashtable<nsIDHashKey, nsFactoryEntry*> mFactories; + nsDataHashtable<nsCStringHashKey, nsFactoryEntry*> mContractIDs; + + SafeMutex mLock; + + static void InitializeStaticModules(); + static void InitializeModuleLocations(); + + struct ComponentLocation + { + NSLocationType type; + mozilla::FileLocation location; + }; + + class ComponentLocationComparator + { + public: + bool Equals(const ComponentLocation& aA, const ComponentLocation& aB) const + { + return (aA.type == aB.type && aA.location.Equals(aB.location)); + } + }; + + static nsTArray<const mozilla::Module*>* sStaticModules; + static nsTArray<ComponentLocation>* sModuleLocations; + + nsNativeModuleLoader mNativeModuleLoader; + + class KnownModule + { + public: + /** + * Static or binary module. + */ + KnownModule(const mozilla::Module* aModule, mozilla::FileLocation& aFile) + : mModule(aModule) + , mFile(aFile) + , mLoaded(false) + , mFailed(false) + { + } + + explicit KnownModule(const mozilla::Module* aModule) + : mModule(aModule) + , mLoaded(false) + , mFailed(false) + { + } + + explicit KnownModule(mozilla::FileLocation& aFile) + : mModule(nullptr) + , mFile(aFile) + , mLoader(nullptr) + , mLoaded(false) + , mFailed(false) + { + } + + ~KnownModule() + { + if (mLoaded && mModule->unloadProc) { + mModule->unloadProc(); + } + } + + bool EnsureLoader(); + bool Load(); + + const mozilla::Module* Module() const { return mModule; } + + /** + * For error logging, get a description of this module, either the + * file path, or <static module>. + */ + nsCString Description() const; + + private: + const mozilla::Module* mModule; + mozilla::FileLocation mFile; + nsCOMPtr<mozilla::ModuleLoader> mLoader; + bool mLoaded; + bool mFailed; + }; + + // The KnownModule is kept alive by these members, it is + // referenced by pointer from the factory entries. + nsTArray<nsAutoPtr<KnownModule>> mKnownStaticModules; + // The key is the URI string of the module + nsClassHashtable<nsCStringHashKey, KnownModule> mKnownModules; + + // Mutex not held + void RegisterModule(const mozilla::Module* aModule, + mozilla::FileLocation* aFile); + + + // Mutex held + void RegisterCIDEntryLocked(const mozilla::Module::CIDEntry* aEntry, + KnownModule* aModule); + void RegisterContractIDLocked(const mozilla::Module::ContractIDEntry* aEntry); + + // Mutex not held + void RegisterManifest(NSLocationType aType, mozilla::FileLocation& aFile, + bool aChromeOnly); + + struct ManifestProcessingContext + { + ManifestProcessingContext(NSLocationType aType, + mozilla::FileLocation& aFile, bool aChromeOnly) + : mType(aType) + , mFile(aFile) + , mChromeOnly(aChromeOnly) + { + } + + ~ManifestProcessingContext() {} + + NSLocationType mType; + mozilla::FileLocation mFile; + bool mChromeOnly; + }; + + void ManifestManifest(ManifestProcessingContext& aCx, int aLineNo, + char* const* aArgv); + void ManifestBinaryComponent(ManifestProcessingContext& aCx, int aLineNo, + char* const* aArgv); + void ManifestXPT(ManifestProcessingContext& aCx, int aLineNo, + char* const* aArgv); + void ManifestComponent(ManifestProcessingContext& aCx, int aLineNo, + char* const* aArgv); + void ManifestContract(ManifestProcessingContext& aCx, int aLineNo, + char* const* aArgv); + void ManifestCategory(ManifestProcessingContext& aCx, int aLineNo, + char* const* aArgv); + + void RereadChromeManifests(bool aChromeOnly = true); + + // Shutdown + enum + { + NOT_INITIALIZED, + NORMAL, + SHUTDOWN_IN_PROGRESS, + SHUTDOWN_COMPLETE + } mStatus; + + PLArenaPool mArena; + + struct PendingServiceInfo + { + const nsCID* cid; + PRThread* thread; + }; + + inline PendingServiceInfo* AddPendingService(const nsCID& aServiceCID, + PRThread* aThread); + inline void RemovePendingService(const nsCID& aServiceCID); + inline PRThread* GetPendingServiceThread(const nsCID& aServiceCID) const; + + nsTArray<PendingServiceInfo> mPendingServices; + + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + +private: + ~nsComponentManagerImpl(); +}; + + +#define NS_MAX_FILENAME_LEN 1024 + +#define NS_ERROR_IS_DIR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 24) + +struct nsFactoryEntry +{ + nsFactoryEntry(const mozilla::Module::CIDEntry* aEntry, + nsComponentManagerImpl::KnownModule* aModule); + + // nsIComponentRegistrar.registerFactory support + nsFactoryEntry(const nsCID& aClass, nsIFactory* aFactory); + + ~nsFactoryEntry(); + + already_AddRefed<nsIFactory> GetFactory(); + + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf); + + const mozilla::Module::CIDEntry* mCIDEntry; + nsComponentManagerImpl::KnownModule* mModule; + + nsCOMPtr<nsIFactory> mFactory; + nsCOMPtr<nsISupports> mServiceObject; +}; + +#endif // nsComponentManager_h__ |