This patch removes C++ code related to reading in XPT information from files. (Code related to packaging XPT files will be removed in the next patch.) This includes code in the manifest parser, in addition to the actual code for parsing files. XPT information is now loaded directly from a single static data structure, XPTHeader::kHeader, which will be automatically generated at compile time from .idl files (via .xpt files). Note that the script to do that is not added until part 6 of this patch series, so linking will fail on parts 2 through 5. I inlined XPTInterfaceInfoManager::RegisterXPTHeader into the ctor, because that is the only caller. It feels like the lock there should not be needed any more, but I left it alone for now. The forward declaration of XPTArena in xptiprivate.h is needed because it was being bootlegged via xpt_xdr.h. Some of the data structures in reflect/xptinfo/ (which wrap the xpt_struct.h data structures) are still allocated using XPTArena. Hopefully we can get rid of that in followup work. I also deleted a lot of comments in xpt_struct.h that talk about the on-disk format. I also deleted checking of the major version number, because that should not matter when the XPT information is baked into the executable. MozReview-Commit-ID: 6NJdaCWRBhU
359 lines
9.6 KiB
C++
359 lines
9.6 KiB
C++
/* -*- 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/ArenaAllocator.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 "nsIFactory.h"
|
|
#include "nsIInterfaceRequestor.h"
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
#include "PLDHashTable.h"
|
|
#include "prtime.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsAutoPtr.h"
|
|
#include "nsWeakReference.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;
|
|
|
|
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 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;
|
|
|
|
mozilla::ArenaAllocator<1024*8, 8> 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__
|