Bug 1773770: Part 12 - Remove XPCOM Module infrastructure. r=xpcom-reviewers,nika

Differential Revision: https://phabricator.services.mozilla.com/D149439
This commit is contained in:
Kris Maglione 2022-06-23 23:05:38 +00:00
Родитель 85eac7b7e1
Коммит ca338cab57
7 изменённых файлов: 17 добавлений и 418 удалений

Просмотреть файл

@ -39,9 +39,6 @@ extern bool gXPCOMMainThreadEventsAreDoomed;
#ifdef __cplusplus
# include "nsStringFwd.h"
namespace mozilla {
struct Module;
} // namespace mozilla
#endif
/**

Просмотреть файл

@ -28,7 +28,6 @@ struct XREShellData;
namespace mozilla {
class XREAppData;
struct BootstrapConfig;
struct Module;
} // namespace mozilla
/**
@ -219,11 +218,6 @@ nsresult XRE_GetFileFromPath(const char* aPath, nsIFile** aResult);
*/
nsresult XRE_GetBinaryPath(nsIFile** aResult);
/**
* Get the static module built in to libxul.
*/
const mozilla::Module* XRE_GetStaticModule();
/**
* Lock a profile directory using platform-specific semantics.
*
@ -257,13 +251,6 @@ nsresult XRE_LockProfileDirectory(nsIFile* aDirectory,
nsresult XRE_InitEmbedding2(nsIFile* aLibXULDirectory, nsIFile* aAppDirectory,
nsIDirectoryServiceProvider* aAppDirProvider);
/**
* Register static XPCOM component information.
* This method may be called at any time before or after XRE_main or
* XRE_InitEmbedding.
*/
nsresult XRE_AddStaticComponent(const mozilla::Module* aComponent);
/**
* Register XPCOM components found in an array of files/directories.
* This method may be called at any time before or after XRE_main or

Просмотреть файл

@ -7,9 +7,7 @@
#ifndef mozilla_GenericFactory_h
#define mozilla_GenericFactory_h
#include "mozilla/Attributes.h"
#include "mozilla/Module.h"
#include "nsIFactory.h"
namespace mozilla {
@ -19,10 +17,10 @@ namespace mozilla {
* module.
*/
class GenericFactory final : public nsIFactory {
~GenericFactory() {}
~GenericFactory() = default;
public:
typedef Module::ConstructorProcPtr ConstructorProcPtr;
typedef nsresult (*ConstructorProcPtr)(const nsIID& aIID, void** aResult);
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIFACTORY

Просмотреть файл

@ -8,31 +8,12 @@
#define mozilla_Module_h
#include "nscore.h"
#include "nsID.h"
#include "nsIFactory.h"
#include "nsCOMPtr.h" // for already_AddRefed
namespace mozilla {
/**
* A module implements one or more XPCOM components. This structure is used
* for binary modules.
*/
struct Module {
static const unsigned int kVersion = 103;
struct CIDEntry;
typedef already_AddRefed<nsIFactory> (*GetFactoryProcPtr)(
const Module& module, const CIDEntry& entry);
typedef nsresult (*ConstructorProcPtr)(const nsIID& aIID, void** aResult);
typedef nsresult (*LoadFuncPtr)();
typedef void (*UnloadFuncPtr)();
namespace Module {
/**
* This selector allows CIDEntrys to be marked so that they're only loaded
* This selector allows components to be marked so that they're only loaded
* into certain kinds of processes. Selectors can be combined.
*/
// Note: This must be kept in sync with the selector matching in
@ -88,76 +69,6 @@ struct Module {
NO_TASKS = 0x0,
ALL_TASKS = 0xFFFF,
};
/**
* The constructor callback is an implementation detail of the default binary
* loader and may be null.
*/
struct CIDEntry {
const nsCID* cid;
bool service;
GetFactoryProcPtr getFactoryProc;
ConstructorProcPtr constructorProc;
ProcessSelector processSelector;
};
struct ContractIDEntry {
const char* contractid;
nsID const* cid;
ProcessSelector processSelector;
};
struct CategoryEntry {
const char* category;
const char* entry;
const char* value;
};
/**
* Binary compatibility check, should be kModuleVersion.
*/
unsigned int mVersion;
/**
* An array of CIDs (class IDs) implemented by this module. The final entry
* should be { nullptr }.
*/
const CIDEntry* mCIDs;
/**
* An array of mappings from contractid to CID. The final entry should
* be { nullptr }.
*/
const ContractIDEntry* mContractIDs;
/**
* An array of category manager entries. The final entry should be
* { nullptr }.
*/
const CategoryEntry* mCategoryEntries;
/**
* When the component manager tries to get the factory for a CID, it first
* checks for this module-level getfactory callback. If this function is
* not implemented, it checks the CIDEntry getfactory callback. If that is
* also nullptr, a generic factory is generated using the CIDEntry
* constructor callback which must be non-nullptr.
*/
GetFactoryProcPtr getFactoryProc;
/**
* Optional Function which are called when this module is loaded and
* at shutdown. These are not C++ constructor/destructors to avoid
* calling them too early in startup or too late in shutdown.
*/
LoadFuncPtr loadProc;
UnloadFuncPtr unloadProc;
/**
* Optional flags which control whether the module loads on a process-type
* basis.
*/
ProcessSelector selector;
};
} // namespace mozilla

Просмотреть файл

@ -9,6 +9,7 @@
#include <type_traits>
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/Attributes.h"
#include "mozilla/Module.h"

Просмотреть файл

@ -163,7 +163,7 @@ class MOZ_STACK_CLASS EntryWrapper final {
return mEntry.match((Matcher()))
const nsID& CID() {
MATCH(const nsID&, return *entry->mCIDEntry->cid, return entry->CID());
MATCH(const nsID&, return entry->mCID, return entry->CID());
}
already_AddRefed<nsIFactory> GetFactory() {
@ -202,14 +202,11 @@ class MOZ_STACK_CLASS EntryWrapper final {
}
/**
* Returns the description string for the module this entry belongs to. For
* static entries, always returns "<unknown module>".
* Returns the description string for the module this entry belongs to.
* Currently always returns "<unknown module>".
*/
nsCString ModuleDescription() {
MATCH(nsCString,
return entry->mModule ? entry->mModule->Description()
: "<unknown module>"_ns,
return "<unknown module>"_ns);
return "<unknown module>"_ns;
}
private:
@ -271,17 +268,6 @@ nsComponentManagerImpl::nsComponentManagerImpl()
mLock("nsComponentManagerImpl.mLock"),
mStatus(NOT_INITIALIZED) {}
static nsTArray<const mozilla::Module*>* sExtraStaticModules;
/* static */
void nsComponentManagerImpl::InitializeStaticModules() {
if (sExtraStaticModules) {
return;
}
sExtraStaticModules = new nsTArray<const mozilla::Module*>;
}
nsTArray<nsComponentManagerImpl::ComponentLocation>*
nsComponentManagerImpl::sModuleLocations;
@ -350,14 +336,8 @@ nsresult nsComponentManagerImpl::Init() {
nsCOMPtr<nsIFile> appDir =
GetLocationFromDirectoryService(NS_XPCOM_CURRENT_PROCESS_DIR);
InitializeStaticModules();
nsCategoryManager::GetSingleton()->SuppressNotifications(true);
for (uint32_t i = 0; i < sExtraStaticModules->Length(); ++i) {
RegisterModule((*sExtraStaticModules)[i]);
}
auto* catMan = nsCategoryManager::GetSingleton();
for (const auto& cat : gStaticCategories) {
for (const auto& entry : cat) {
@ -468,8 +448,6 @@ nsresult nsComponentManagerImpl::Init() {
return NS_OK;
}
static const int kModuleVersionWithSelector = 51;
template <typename T>
static void AssertNotMallocAllocated(T* aPtr) {
#if defined(DEBUG) && defined(MOZ_MEMORY)
@ -510,140 +488,6 @@ static void AssertNotStackAllocated(T* aPtr) {
#endif
}
static inline nsCString AsLiteralCString(const char* aStr) {
AssertNotMallocAllocated(aStr);
AssertNotStackAllocated(aStr);
nsCString str;
str.AssignLiteral(aStr, strlen(aStr));
return str;
}
void nsComponentManagerImpl::RegisterModule(const mozilla::Module* aModule) {
mLock.AssertNotCurrentThreadOwns();
if (aModule->mVersion >= kModuleVersionWithSelector &&
!ProcessSelectorMatches(aModule->selector)) {
return;
}
{
// Scope the monitor so that we don't hold it while calling into the
// category manager.
MonitorAutoLock lock(mLock);
KnownModule* m = new KnownModule(aModule);
mKnownStaticModules.AppendElement(m);
if (aModule->mCIDs) {
const mozilla::Module::CIDEntry* entry;
for (entry = aModule->mCIDs; entry->cid; ++entry) {
RegisterCIDEntryLocked(entry, m);
}
}
if (aModule->mContractIDs) {
const mozilla::Module::ContractIDEntry* entry;
for (entry = aModule->mContractIDs; entry->contractid; ++entry) {
RegisterContractIDLocked(entry);
}
MOZ_ASSERT(!entry->cid, "Incorrectly terminated contract list");
}
}
if (aModule->mCategoryEntries) {
const mozilla::Module::CategoryEntry* entry;
for (entry = aModule->mCategoryEntries; entry->category; ++entry)
nsCategoryManager::GetSingleton()->AddCategoryEntry(
AsLiteralCString(entry->category), AsLiteralCString(entry->entry),
AsLiteralCString(entry->value));
}
}
void nsComponentManagerImpl::RegisterCIDEntryLocked(
const mozilla::Module::CIDEntry* aEntry, KnownModule* aModule) {
mLock.AssertCurrentThreadOwns();
if (!ProcessSelectorMatches(aEntry->processSelector)) {
return;
}
#ifdef DEBUG
// If we're still in the static initialization phase, check that we're not
// registering something that was already registered.
if (mStatus != NORMAL) {
if (StaticComponents::LookupByCID(*aEntry->cid)) {
MOZ_CRASH_UNSAFE_PRINTF(
"While registering XPCOM module %s, trying to re-register CID '%s' "
"already registered by a static component.",
aModule->Description().get(), AutoIDString(*aEntry->cid).get());
}
}
#endif
mFactories.WithEntryHandle(aEntry->cid, [&](auto&& entry) {
mLock.AssertCurrentThreadOwns();
if (entry) {
nsFactoryEntry* f = entry.Data();
NS_WARNING("Re-registering a CID?");
nsCString existing;
if (f->mModule) {
existing = f->mModule->Description();
} else {
existing = "<unknown module>";
}
MonitorAutoUnlock unlock(mLock);
LogMessage(
"While registering XPCOM module %s, trying to re-register CID '%s' "
"already registered by %s.",
aModule->Description().get(), AutoIDString(*aEntry->cid).get(),
existing.get());
} else {
entry.Insert(new nsFactoryEntry(aEntry, aModule));
}
});
}
void nsComponentManagerImpl::RegisterContractIDLocked(
const mozilla::Module::ContractIDEntry* aEntry) {
mLock.AssertCurrentThreadOwns();
if (!ProcessSelectorMatches(aEntry->processSelector)) {
return;
}
#ifdef DEBUG
// If we're still in the static initialization phase, check that we're not
// registering something that was already registered.
if (mStatus != NORMAL) {
if (const StaticModule* module = StaticComponents::LookupByContractID(
nsAutoCString(aEntry->contractid))) {
MOZ_CRASH_UNSAFE_PRINTF(
"Could not map contract ID '%s' to CID %s because it is already "
"mapped to CID %s.",
aEntry->contractid, AutoIDString(*aEntry->cid).get(),
AutoIDString(module->CID()).get());
}
}
#endif
nsFactoryEntry* f = mFactories.Get(aEntry->cid);
if (!f) {
NS_WARNING("No CID found when attempting to map contract ID");
MonitorAutoUnlock unlock(mLock);
LogMessage(
"Could not map contract ID '%s' to CID %s because no implementation of "
"the CID is registered.",
aEntry->contractid, AutoIDString(*aEntry->cid).get());
return;
}
mContractIDs.InsertOrUpdate(AsLiteralCString(aEntry->contractid), f);
}
static void DoRegisterManifest(NSLocationType aType, FileLocation& aFile,
bool aChromeOnly) {
auto result = URLPreloader::Read(aFile);
@ -693,28 +537,6 @@ void nsComponentManagerImpl::RereadChromeManifests(bool aChromeOnly) {
}
}
bool nsComponentManagerImpl::KnownModule::Load() {
if (mFailed) {
return false;
}
MOZ_ASSERT(mModule);
if (!mLoaded) {
if (mModule->loadProc) {
nsresult rv = mModule->loadProc();
if (NS_FAILED(rv)) {
mFailed = true;
return false;
}
}
mLoaded = true;
}
return true;
}
nsCString nsComponentManagerImpl::KnownModule::Description() const {
return "<static module>"_ns;
}
nsresult nsComponentManagerImpl::Shutdown(void) {
MOZ_ASSERT(NORMAL == mStatus);
@ -729,11 +551,9 @@ nsresult nsComponentManagerImpl::Shutdown(void) {
// Release all cached factories
mContractIDs.Clear();
mFactories.Clear(); // XXX release the objects, don't just clear
mKnownStaticModules.Clear();
StaticComponents::Shutdown();
delete sExtraStaticModules;
delete sModuleLocations;
mStatus = SHUTDOWN_COMPLETE;
@ -799,7 +619,7 @@ Maybe<EntryWrapper> nsComponentManagerImpl::LookupByContractID(
// UnregisterFactory might have left a stale nsFactoryEntry in
// mContractIDs, so we should check to see whether this entry has
// anything useful.
if (entry->mModule || entry->mFactory || entry->mServiceObject) {
if (entry->mFactory || entry->mServiceObject) {
return Some(EntryWrapper(entry));
}
}
@ -1382,11 +1202,11 @@ nsComponentManagerImpl::RegisterFactory(const nsCID& aClass, const char* aName,
auto f = MakeUnique<nsFactoryEntry>(aClass, aFactory);
MonitorAutoLock lock(mLock);
return mFactories.WithEntryHandle(f->mCIDEntry->cid, [&](auto&& entry) {
return mFactories.WithEntryHandle(&f->mCID, [&](auto&& entry) {
if (entry) {
return NS_ERROR_FACTORY_EXISTS;
}
if (StaticComponents::LookupByCID(*f->mCIDEntry->cid)) {
if (StaticComponents::LookupByCID(f->mCID)) {
return NS_ERROR_FACTORY_EXISTS;
}
if (aContractID) {
@ -1541,20 +1361,16 @@ size_t nsComponentManagerImpl::SizeOfIncludingThis(
n += key.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
}
n += sExtraStaticModules->ShallowSizeOfIncludingThis(aMallocSizeOf);
if (sModuleLocations) {
n += sModuleLocations->ShallowSizeOfIncludingThis(aMallocSizeOf);
}
n += mKnownStaticModules.ShallowSizeOfExcludingThis(aMallocSizeOf);
n += mPendingServices.ShallowSizeOfExcludingThis(aMallocSizeOf);
// Measurement of the following members may be added later if DMD finds it is
// worthwhile:
// - mMon
// - sModuleLocations' entries
// - mKnownStaticModules' entries?
return n;
}
@ -1563,63 +1379,13 @@ size_t nsComponentManagerImpl::SizeOfIncludingThis(
// nsFactoryEntry
////////////////////////////////////////////////////////////////////////////////
nsFactoryEntry::nsFactoryEntry(const mozilla::Module::CIDEntry* aEntry,
nsComponentManagerImpl::KnownModule* aModule)
: mCIDEntry(aEntry), mModule(aModule) {}
nsFactoryEntry::nsFactoryEntry(const nsCID& aCID, nsIFactory* aFactory)
: mCIDEntry(nullptr), mModule(nullptr), mFactory(aFactory) {
auto* e = new mozilla::Module::CIDEntry();
auto* cid = new nsCID;
*cid = aCID;
e->cid = cid;
mCIDEntry = e;
}
nsFactoryEntry::~nsFactoryEntry() {
// If this was a RegisterFactory entry, we own the CIDEntry/CID
if (!mModule) {
delete mCIDEntry->cid;
delete mCIDEntry;
}
: mCID(aCID), mFactory(aFactory) {
}
already_AddRefed<nsIFactory> nsFactoryEntry::GetFactory() {
nsComponentManagerImpl::gComponentManager->mLock.AssertNotCurrentThreadOwns();
if (!mFactory) {
// RegisterFactory then UnregisterFactory can leave an entry in mContractIDs
// pointing to an unusable nsFactoryEntry.
if (!mModule) {
return nullptr;
}
if (!mModule->Load()) {
return nullptr;
}
// Don't set mFactory directly, it needs to be locked
nsCOMPtr<nsIFactory> factory;
if (mModule->Module()->getFactoryProc) {
factory =
mModule->Module()->getFactoryProc(*mModule->Module(), *mCIDEntry);
} else if (mCIDEntry->getFactoryProc) {
factory = mCIDEntry->getFactoryProc(*mModule->Module(), *mCIDEntry);
} else {
NS_ASSERTION(mCIDEntry->constructorProc, "no getfactory or constructor");
factory = new mozilla::GenericFactory(mCIDEntry->constructorProc);
}
if (!factory) {
return nullptr;
}
MonitorAutoLock lock(nsComponentManagerImpl::gComponentManager->mLock);
// Threads can race to set mFactory
if (!mFactory) {
factory.swap(mFactory);
}
}
nsCOMPtr<nsIFactory> factory = mFactory;
return factory.forget();
}
@ -1635,8 +1401,7 @@ size_t nsFactoryEntry::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) {
// Measurement of the following members may be added later if DMD finds it is
// worthwhile:
// - mCIDEntry;
// - mModule;
// - mCID;
// - mFactory;
// - mServiceObject;
@ -1674,20 +1439,6 @@ nsresult NS_GetComponentRegistrar(nsIComponentRegistrar** aResult) {
return NS_OK;
}
EXPORT_XPCOM_API(nsresult)
XRE_AddStaticComponent(const mozilla::Module* aComponent) {
nsComponentManagerImpl::InitializeStaticModules();
sExtraStaticModules->AppendElement(aComponent);
if (nsComponentManagerImpl::gComponentManager &&
nsComponentManagerImpl::NORMAL ==
nsComponentManagerImpl::gComponentManager->mStatus) {
nsComponentManagerImpl::gComponentManager->RegisterModule(aComponent);
}
return NS_OK;
}
NS_IMETHODIMP
nsComponentManagerImpl::AddBootstrappedManifestLocation(nsIFile* aLocation) {
NS_ENSURE_ARG_POINTER(aLocation);

Просмотреть файл

@ -137,48 +137,6 @@ class nsComponentManagerImpl final : public nsIComponentManager,
static nsTArray<ComponentLocation>* sModuleLocations;
class KnownModule {
public:
/**
* Static or binary module.
*/
explicit KnownModule(const mozilla::Module* aModule)
: mModule(aModule), mLoaded(false), mFailed(false) {}
~KnownModule() {
if (mLoaded && mModule->unloadProc) {
mModule->unloadProc();
}
}
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;
bool mLoaded;
bool mFailed;
};
// The KnownModule is kept alive by these members, it is
// referenced by pointer from the factory entries.
nsTArray<mozilla::UniquePtr<KnownModule>> mKnownStaticModules;
// Mutex not held
void RegisterModule(const mozilla::Module* aModule);
// 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);
@ -240,13 +198,10 @@ class nsComponentManagerImpl final : public nsIComponentManager,
#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();
~nsFactoryEntry() = default;
already_AddRefed<nsIFactory> GetFactory();
@ -254,8 +209,7 @@ struct nsFactoryEntry {
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
const mozilla::Module::CIDEntry* mCIDEntry;
nsComponentManagerImpl::KnownModule* mModule;
const nsCID mCID;
nsCOMPtr<nsIFactory> mFactory;
nsCOMPtr<nsISupports> mServiceObject;