diff -r 000000000000 -r 6474c204b198 xpcom/components/nsComponentManager.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xpcom/components/nsComponentManager.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,349 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* 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/MemoryReporting.h" +#include "mozilla/Module.h" +#include "mozilla/ModuleLoader.h" +#include "mozilla/Mutex.h" +#include "nsXULAppAPI.h" +#include "nsNativeComponentLoader.h" +#include "nsIFactory.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "pldhash.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: + SafeMutex(const char* name) + : mMutex(name) + , 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; + volatile PRThread* mOwnerThread; +}; + +typedef mozilla::BaseAutoLock SafeMutexAutoLock; +typedef mozilla::BaseAutoUnlock SafeMutexAutoUnlock; + +class nsComponentManagerImpl MOZ_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 LoaderForExtension(const nsACString& aExt); + nsInterfaceHashtable mLoaderMap; + + already_AddRefed FindFactory(const nsCID& aClass); + already_AddRefed FindFactory(const char *contractID, + uint32_t aContractIDLen); + + already_AddRefed LoadFactory(nsFactoryEntry *aEntry); + + nsFactoryEntry *GetFactoryEntry(const char *aContractID, + uint32_t aContractIDLen); + nsFactoryEntry *GetFactoryEntry(const nsCID &aClass); + + nsDataHashtable mFactories; + nsDataHashtable mContractIDs; + + SafeMutex mLock; + + static void InitializeStaticModules(); + static void InitializeModuleLocations(); + + struct ComponentLocation + { + NSLocationType type; + mozilla::FileLocation location; + }; + + class ComponentLocationComparator + { + public: + bool Equals(const ComponentLocation& a, const ComponentLocation& b) const + { + return (a.type == b.type && a.location.Equals(b.location)); + } + }; + + static nsTArray* sStaticModules; + static nsTArray* 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) + { } + + KnownModule(const mozilla::Module* aModule) + : mModule(aModule) + , mLoaded(false) + , mFailed(false) + { } + + 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 . + */ + nsCString Description() const; + + private: + const mozilla::Module* mModule; + mozilla::FileLocation mFile; + nsCOMPtr mLoader; + bool mLoaded; + bool mFailed; + }; + + // The KnownModule is kept alive by these members, it is + // referenced by pointer from the factory entries. + nsTArray< nsAutoPtr > mKnownStaticModules; + // The key is the URI string of the module + nsClassHashtable 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& cx, int lineno, char *const * argv); + void ManifestBinaryComponent(ManifestProcessingContext& cx, int lineno, char *const * argv); + void ManifestXPT(ManifestProcessingContext& cx, int lineno, char *const * argv); + void ManifestComponent(ManifestProcessingContext& cx, int lineno, char *const * argv); + void ManifestContract(ManifestProcessingContext& cx, int lineno, char* const * argv); + void ManifestCategory(ManifestProcessingContext& cx, int lineno, char* const * argv); + + 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 mPendingServices; + + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf); + +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* entry, + nsComponentManagerImpl::KnownModule* module); + + // nsIComponentRegistrar.registerFactory support + nsFactoryEntry(const nsCID& aClass, nsIFactory* factory); + + ~nsFactoryEntry(); + + already_AddRefed GetFactory(); + + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf); + + const mozilla::Module::CIDEntry* mCIDEntry; + nsComponentManagerImpl::KnownModule* mModule; + + nsCOMPtr mFactory; + nsCOMPtr mServiceObject; +}; + +#endif // nsComponentManager_h__