|
@@ -1,902 +0,0 @@
|
|
|
-# HG changeset patch
|
|
|
-# User Bill Gianopoulos <wgianopoulos@gmail.com>
|
|
|
-# Date 1657108142 0
|
|
|
-Backout bug 1773770 part 12.
|
|
|
-Bug 1773770: Part 12 - Remove XPCOM Module infrastructure.
|
|
|
-
|
|
|
-diff --git a/xpcom/build/nsXPCOM.h b/xpcom/build/nsXPCOM.h
|
|
|
---- a/xpcom/build/nsXPCOM.h
|
|
|
-+++ b/xpcom/build/nsXPCOM.h
|
|
|
-@@ -34,16 +34,19 @@ DECL_CLASS(nsIDebug2);
|
|
|
- extern bool gXPCOMShuttingDown;
|
|
|
- extern mozilla::Atomic<bool, mozilla::SequentiallyConsistent>
|
|
|
- gXPCOMThreadsShutDown;
|
|
|
- extern bool gXPCOMMainThreadEventsAreDoomed;
|
|
|
- #endif
|
|
|
-
|
|
|
- #ifdef __cplusplus
|
|
|
- # include "nsStringFwd.h"
|
|
|
-+namespace mozilla {
|
|
|
-+struct Module;
|
|
|
-+} // namespace mozilla
|
|
|
- #endif
|
|
|
-
|
|
|
- /**
|
|
|
- * Initialises XPCOM. You must call one of the NS_InitXPCOM methods
|
|
|
- * before proceeding to use xpcom. The one exception is that you may
|
|
|
- * call NS_NewLocalFile to create a nsIFile.
|
|
|
- *
|
|
|
- * @note Use <CODE>NS_NewLocalFile</CODE> or <CODE>NS_NewNativeLocalFile</CODE>
|
|
|
-diff --git a/xpcom/build/nsXULAppAPI.h b/xpcom/build/nsXULAppAPI.h
|
|
|
---- a/xpcom/build/nsXULAppAPI.h
|
|
|
-+++ b/xpcom/build/nsXULAppAPI.h
|
|
|
-@@ -23,16 +23,17 @@ class nsIFile;
|
|
|
- class nsISupports;
|
|
|
- struct JSContext;
|
|
|
- struct XREChildData;
|
|
|
- struct XREShellData;
|
|
|
-
|
|
|
- namespace mozilla {
|
|
|
- class XREAppData;
|
|
|
- struct BootstrapConfig;
|
|
|
-+struct Module;
|
|
|
- } // namespace mozilla
|
|
|
-
|
|
|
- /**
|
|
|
- * A directory service key which provides the platform-correct "application
|
|
|
- * data" directory as follows, where $name and $vendor are as defined above and
|
|
|
- * $vendor is optional:
|
|
|
- *
|
|
|
- * Windows:
|
|
|
-@@ -214,16 +215,21 @@ int XRE_main(int argc, char* argv[], con
|
|
|
- nsresult XRE_GetFileFromPath(const char* aPath, nsIFile** aResult);
|
|
|
-
|
|
|
- /**
|
|
|
- * Get the path of the running application binary and store it in 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.
|
|
|
- *
|
|
|
- * @param aDirectory The profile directory to lock.
|
|
|
- * @param aLockObject An opaque lock object. The directory will remain locked
|
|
|
- * as long as the XPCOM reference is held.
|
|
|
- */
|
|
|
- nsresult XRE_LockProfileDirectory(nsIFile* aDirectory,
|
|
|
- nsISupports** aLockObject);
|
|
|
-@@ -247,16 +253,23 @@ nsresult XRE_LockProfileDirectory(nsIFil
|
|
|
- * a given process. Use XRE_TermEmbedding to clean up and free
|
|
|
- * resources allocated by XRE_InitEmbedding.
|
|
|
- */
|
|
|
-
|
|
|
- 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
|
|
|
- * XRE_InitEmbedding.
|
|
|
- *
|
|
|
- * @param aFiles An array of files or directories.
|
|
|
- * @param aFileCount the number of items in the aFiles array.
|
|
|
- * @note appdir/components is registered automatically.
|
|
|
- *
|
|
|
-diff --git a/xpcom/components/GenericFactory.h b/xpcom/components/GenericFactory.h
|
|
|
---- a/xpcom/components/GenericFactory.h
|
|
|
-+++ b/xpcom/components/GenericFactory.h
|
|
|
-@@ -2,30 +2,32 @@
|
|
|
- /* 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 mozilla_GenericFactory_h
|
|
|
- #define mozilla_GenericFactory_h
|
|
|
-
|
|
|
--#include "nsIFactory.h"
|
|
|
-+#include "mozilla/Attributes.h"
|
|
|
-+
|
|
|
-+#include "mozilla/Module.h"
|
|
|
-
|
|
|
- namespace mozilla {
|
|
|
-
|
|
|
- /**
|
|
|
- * A generic factory which uses a constructor function to create instances.
|
|
|
- * This class is intended for use by the component manager and the generic
|
|
|
- * module.
|
|
|
- */
|
|
|
- class GenericFactory final : public nsIFactory {
|
|
|
-- ~GenericFactory() = default;
|
|
|
-+ ~GenericFactory() {}
|
|
|
-
|
|
|
- public:
|
|
|
-- typedef nsresult (*ConstructorProcPtr)(const nsIID& aIID, void** aResult);
|
|
|
-+ typedef Module::ConstructorProcPtr ConstructorProcPtr;
|
|
|
-
|
|
|
- NS_DECL_THREADSAFE_ISUPPORTS
|
|
|
- NS_DECL_NSIFACTORY
|
|
|
-
|
|
|
- explicit GenericFactory(ConstructorProcPtr aCtor) : mCtor(aCtor) {
|
|
|
- NS_ASSERTION(mCtor, "GenericFactory with no constructor");
|
|
|
- }
|
|
|
-
|
|
|
-diff --git a/xpcom/components/Module.h b/xpcom/components/Module.h
|
|
|
---- a/xpcom/components/Module.h
|
|
|
-+++ b/xpcom/components/Module.h
|
|
|
-@@ -3,22 +3,41 @@
|
|
|
- /* 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 mozilla_Module_h
|
|
|
- #define mozilla_Module_h
|
|
|
-
|
|
|
- #include "nscore.h"
|
|
|
-+#include "nsID.h"
|
|
|
-+#include "nsIFactory.h"
|
|
|
-+#include "nsCOMPtr.h" // for already_AddRefed
|
|
|
-
|
|
|
- namespace mozilla {
|
|
|
-
|
|
|
--namespace Module {
|
|
|
-+/**
|
|
|
-+ * A module implements one or more XPCOM components. This structure is used
|
|
|
-+ * for binary modules.
|
|
|
-+ */
|
|
|
-+struct Module {
|
|
|
-+ static const unsigned int kVersion = 104;
|
|
|
-+
|
|
|
-+ 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)();
|
|
|
-+
|
|
|
- /**
|
|
|
-- * This selector allows components to be marked so that they're only loaded
|
|
|
-+ * This selector allows CIDEntrys 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
|
|
|
- // nsComponentManager.cpp.
|
|
|
- enum ProcessSelector {
|
|
|
- ANY_PROCESS = 0x0,
|
|
|
- MAIN_PROCESS_ONLY = 0x1,
|
|
|
- CONTENT_PROCESS_ONLY = 0x2,
|
|
|
-@@ -64,13 +83,83 @@ namespace Module {
|
|
|
- * not loaded when in backgroundtask mode.
|
|
|
- */
|
|
|
- // Note: This must be kept in sync with the selector matching in
|
|
|
- // StaticComponents.cpp.in.
|
|
|
- enum BackgroundTasksSelector {
|
|
|
- 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
|
|
|
-
|
|
|
- #endif // mozilla_Module_h
|
|
|
-diff --git a/xpcom/components/ModuleUtils.h b/xpcom/components/ModuleUtils.h
|
|
|
---- a/xpcom/components/ModuleUtils.h
|
|
|
-+++ b/xpcom/components/ModuleUtils.h
|
|
|
-@@ -4,17 +4,16 @@
|
|
|
- * 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 mozilla_GenericModule_h
|
|
|
- #define mozilla_GenericModule_h
|
|
|
-
|
|
|
- #include <type_traits>
|
|
|
-
|
|
|
--#include "mozilla/AlreadyAddRefed.h"
|
|
|
- #include "mozilla/Attributes.h"
|
|
|
- #include "mozilla/Module.h"
|
|
|
-
|
|
|
- #define NS_GENERIC_FACTORY_CONSTRUCTOR(_InstanceClass) \
|
|
|
- static nsresult _InstanceClass##Constructor(REFNSIID aIID, void** aResult) { \
|
|
|
- RefPtr<_InstanceClass> inst; \
|
|
|
- \
|
|
|
- *aResult = nullptr; \
|
|
|
-diff --git a/xpcom/components/nsComponentManager.cpp b/xpcom/components/nsComponentManager.cpp
|
|
|
---- a/xpcom/components/nsComponentManager.cpp
|
|
|
-+++ b/xpcom/components/nsComponentManager.cpp
|
|
|
-@@ -158,17 +158,17 @@ class MOZ_STACK_CLASS EntryWrapper final
|
|
|
- #define MATCH(type, ifFactory, ifStatic) \
|
|
|
- struct Matcher { \
|
|
|
- type operator()(nsFactoryEntry* entry) { ifFactory; } \
|
|
|
- type operator()(const StaticModule* entry) { ifStatic; } \
|
|
|
- }; \
|
|
|
- return mEntry.match((Matcher()))
|
|
|
-
|
|
|
- const nsID& CID() {
|
|
|
-- MATCH(const nsID&, return entry->mCID, return entry->CID());
|
|
|
-+ MATCH(const nsID&, return *entry->mCIDEntry->cid, return entry->CID());
|
|
|
- }
|
|
|
-
|
|
|
- already_AddRefed<nsIFactory> GetFactory() {
|
|
|
- MATCH(already_AddRefed<nsIFactory>, return entry->GetFactory(),
|
|
|
- return entry->GetFactory());
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
-@@ -197,21 +197,24 @@ class MOZ_STACK_CLASS EntryWrapper final
|
|
|
- mEntry.as<nsFactoryEntry*>()->mServiceObject = aInst;
|
|
|
- } else {
|
|
|
- return mEntry.as<const StaticModule*>()->SetServiceInstance(
|
|
|
- std::move(aInst));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
-- * Returns the description string for the module this entry belongs to.
|
|
|
-- * Currently always returns "<unknown module>".
|
|
|
-+ * Returns the description string for the module this entry belongs to. For
|
|
|
-+ * static entries, always returns "<unknown module>".
|
|
|
- */
|
|
|
- nsCString ModuleDescription() {
|
|
|
-- return "<unknown module>"_ns;
|
|
|
-+ MATCH(nsCString,
|
|
|
-+ return entry->mModule ? entry->mModule->Description()
|
|
|
-+ : "<unknown module>"_ns,
|
|
|
-+ return "<unknown module>"_ns);
|
|
|
- }
|
|
|
-
|
|
|
- private:
|
|
|
- Variant<nsFactoryEntry*, const StaticModule*> mEntry;
|
|
|
- };
|
|
|
-
|
|
|
- } // namespace
|
|
|
-
|
|
|
-@@ -263,16 +266,27 @@ nsresult nsComponentManagerImpl::Create(
|
|
|
- static const int CONTRACTID_HASHTABLE_INITIAL_LENGTH = 8;
|
|
|
-
|
|
|
- nsComponentManagerImpl::nsComponentManagerImpl()
|
|
|
- : mFactories(CONTRACTID_HASHTABLE_INITIAL_LENGTH),
|
|
|
- mContractIDs(CONTRACTID_HASHTABLE_INITIAL_LENGTH),
|
|
|
- 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;
|
|
|
-
|
|
|
- /* static */
|
|
|
- void nsComponentManagerImpl::InitializeModuleLocations() {
|
|
|
- if (sModuleLocations) {
|
|
|
- return;
|
|
|
- }
|
|
|
-@@ -331,18 +345,24 @@ nsresult nsComponentManagerImpl::Init()
|
|
|
- }
|
|
|
-
|
|
|
- MOZ_ASSERT(NOT_INITIALIZED == mStatus);
|
|
|
-
|
|
|
- nsCOMPtr<nsIFile> greDir = GetLocationFromDirectoryService(NS_GRE_DIR);
|
|
|
- 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) {
|
|
|
- if (entry.Active()) {
|
|
|
- catMan->AddCategoryEntry(cat.Name(), entry.Entry(), entry.Value());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-@@ -443,16 +463,18 @@ nsresult nsComponentManagerImpl::Init()
|
|
|
- MOZ_ASSERT(!XRE_IsContentProcess() ||
|
|
|
- CONTRACTID_HASHTABLE_INITIAL_LENGTH <= 8 ||
|
|
|
- mFactories.Count() > CONTRACTID_HASHTABLE_INITIAL_LENGTH / 3,
|
|
|
- "Initial component hashtable size is too large");
|
|
|
-
|
|
|
- return NS_OK;
|
|
|
- }
|
|
|
-
|
|
|
-+static const int kModuleVersionWithSelector = 51;
|
|
|
-+
|
|
|
- template <typename T>
|
|
|
- static void AssertNotMallocAllocated(T* aPtr) {
|
|
|
- #if defined(DEBUG) && defined(MOZ_MEMORY)
|
|
|
- jemalloc_ptr_info_t info;
|
|
|
- jemalloc_ptr_info((void*)aPtr, &info);
|
|
|
- MOZ_ASSERT(info.tag == TagUnknown);
|
|
|
- #endif
|
|
|
- }
|
|
|
-@@ -483,16 +505,150 @@ static void AssertNotStackAllocated(T* a
|
|
|
- #ifdef DEBUG
|
|
|
- static constexpr size_t kFuzz = 2048;
|
|
|
-
|
|
|
- MOZ_ASSERT(uintptr_t(aPtr) < uintptr_t(&aPtr) ||
|
|
|
- uintptr_t(aPtr) > uintptr_t(&aPtr) + kFuzz);
|
|
|
- #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);
|
|
|
- if (result.isOk()) {
|
|
|
- nsCString buf(result.unwrap());
|
|
|
- ParseManifest(aType, aFile, buf.BeginWriting(), aChromeOnly);
|
|
|
- } else if (NS_BOOTSTRAPPED_LOCATION != aType) {
|
|
|
- nsCString uri;
|
|
|
-@@ -532,33 +688,57 @@ void nsComponentManagerImpl::RereadChrom
|
|
|
- }
|
|
|
-
|
|
|
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
|
- if (obs) {
|
|
|
- obs->NotifyObservers(nullptr, "chrome-manifests-loaded", nullptr);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-+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);
|
|
|
-
|
|
|
- mStatus = SHUTDOWN_IN_PROGRESS;
|
|
|
-
|
|
|
- // Shutdown the component manager
|
|
|
- MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
|
|
|
- ("nsComponentManager: Beginning Shutdown."));
|
|
|
-
|
|
|
- UnregisterWeakMemoryReporter(this);
|
|
|
-
|
|
|
- // 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;
|
|
|
-
|
|
|
- MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
|
|
|
- ("nsComponentManager: Shutdown complete."));
|
|
|
-
|
|
|
- return NS_OK;
|
|
|
-@@ -614,17 +794,17 @@ Maybe<EntryWrapper> nsComponentManagerIm
|
|
|
- if (const StaticModule* module =
|
|
|
- StaticComponents::LookupByContractID(aContractID)) {
|
|
|
- return Some(EntryWrapper(module));
|
|
|
- }
|
|
|
- if (nsFactoryEntry* entry = mContractIDs.Get(aContractID)) {
|
|
|
- // UnregisterFactory might have left a stale nsFactoryEntry in
|
|
|
- // mContractIDs, so we should check to see whether this entry has
|
|
|
- // anything useful.
|
|
|
-- if (entry->mFactory || entry->mServiceObject) {
|
|
|
-+ if (entry->mModule || entry->mFactory || entry->mServiceObject) {
|
|
|
- return Some(EntryWrapper(entry));
|
|
|
- }
|
|
|
- }
|
|
|
- return Nothing();
|
|
|
- }
|
|
|
-
|
|
|
- already_AddRefed<nsIFactory> nsComponentManagerImpl::FindFactory(
|
|
|
- const nsCID& aClass) {
|
|
|
-@@ -1197,21 +1377,21 @@ nsComponentManagerImpl::RegisterFactory(
|
|
|
- }
|
|
|
- }
|
|
|
- return NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
- }
|
|
|
-
|
|
|
- auto f = MakeUnique<nsFactoryEntry>(aClass, aFactory);
|
|
|
-
|
|
|
- MonitorAutoLock lock(mLock);
|
|
|
-- return mFactories.WithEntryHandle(&f->mCID, [&](auto&& entry) {
|
|
|
-+ return mFactories.WithEntryHandle(f->mCIDEntry->cid, [&](auto&& entry) {
|
|
|
- if (entry) {
|
|
|
- return NS_ERROR_FACTORY_EXISTS;
|
|
|
- }
|
|
|
-- if (StaticComponents::LookupByCID(f->mCID)) {
|
|
|
-+ if (StaticComponents::LookupByCID(*f->mCIDEntry->cid)) {
|
|
|
- return NS_ERROR_FACTORY_EXISTS;
|
|
|
- }
|
|
|
- if (aContractID) {
|
|
|
- nsDependentCString contractID(aContractID);
|
|
|
- mContractIDs.InsertOrUpdate(contractID, f.get());
|
|
|
- // We allow dynamically-registered contract IDs to override static
|
|
|
- // entries, so invalidate any static entry for this contract ID.
|
|
|
- StaticComponents::InvalidateContractID(contractID);
|
|
|
-@@ -1356,57 +1536,112 @@ size_t nsComponentManagerImpl::SizeOfInc
|
|
|
-
|
|
|
- n += mContractIDs.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
|
|
- for (const auto& key : mContractIDs.Keys()) {
|
|
|
- // We don't measure the nsFactoryEntry data because it's owned by
|
|
|
- // mFactories (which is measured above).
|
|
|
- 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;
|
|
|
- }
|
|
|
-
|
|
|
- ////////////////////////////////////////////////////////////////////////////////
|
|
|
- // nsFactoryEntry
|
|
|
- ////////////////////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
-+nsFactoryEntry::nsFactoryEntry(const mozilla::Module::CIDEntry* aEntry,
|
|
|
-+ nsComponentManagerImpl::KnownModule* aModule)
|
|
|
-+ : mCIDEntry(aEntry), mModule(aModule) {}
|
|
|
-+
|
|
|
- nsFactoryEntry::nsFactoryEntry(const nsCID& aCID, nsIFactory* aFactory)
|
|
|
-- : mCID(aCID), mFactory(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;
|
|
|
-+ }
|
|
|
- }
|
|
|
-
|
|
|
- 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();
|
|
|
- }
|
|
|
-
|
|
|
- nsresult nsFactoryEntry::CreateInstance(const nsIID& aIID, void** aResult) {
|
|
|
- nsCOMPtr<nsIFactory> factory = GetFactory();
|
|
|
- NS_ENSURE_TRUE(factory, NS_ERROR_FAILURE);
|
|
|
- return factory->CreateInstance(aIID, aResult);
|
|
|
- }
|
|
|
-
|
|
|
- size_t nsFactoryEntry::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) {
|
|
|
- size_t n = aMallocSizeOf(this);
|
|
|
-
|
|
|
- // Measurement of the following members may be added later if DMD finds it is
|
|
|
- // worthwhile:
|
|
|
-- // - mCID;
|
|
|
-+ // - mCIDEntry;
|
|
|
-+ // - mModule;
|
|
|
- // - mFactory;
|
|
|
- // - mServiceObject;
|
|
|
-
|
|
|
- return n;
|
|
|
- }
|
|
|
-
|
|
|
- ////////////////////////////////////////////////////////////////////////////////
|
|
|
- // Static Access Functions
|
|
|
-@@ -1434,16 +1669,30 @@ nsresult NS_GetComponentRegistrar(nsICom
|
|
|
- if (!nsComponentManagerImpl::gComponentManager) {
|
|
|
- return NS_ERROR_NOT_INITIALIZED;
|
|
|
- }
|
|
|
-
|
|
|
- NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
|
|
|
- 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);
|
|
|
-
|
|
|
- nsString path;
|
|
|
- nsresult rv = aLocation->GetPath(path);
|
|
|
- if (NS_FAILED(rv)) {
|
|
|
- return rv;
|
|
|
-diff --git a/xpcom/components/nsComponentManager.h b/xpcom/components/nsComponentManager.h
|
|
|
---- a/xpcom/components/nsComponentManager.h
|
|
|
-+++ b/xpcom/components/nsComponentManager.h
|
|
|
-@@ -132,16 +132,58 @@ class nsComponentManagerImpl final : pub
|
|
|
- bool Equals(const ComponentLocation& aA,
|
|
|
- const ComponentLocation& aB) const {
|
|
|
- return (aA.type == aB.type && aA.location.Equals(aB.location));
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- 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);
|
|
|
-
|
|
|
- struct ManifestProcessingContext {
|
|
|
- ManifestProcessingContext(NSLocationType aType,
|
|
|
- mozilla::FileLocation& aFile, bool aChromeOnly)
|
|
|
- : mType(aType), mFile(aFile), mChromeOnly(aChromeOnly) {}
|
|
|
-@@ -193,26 +235,30 @@ class nsComponentManagerImpl final : pub
|
|
|
- void** aResult);
|
|
|
- };
|
|
|
-
|
|
|
- #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() = default;
|
|
|
-+ ~nsFactoryEntry();
|
|
|
-
|
|
|
- already_AddRefed<nsIFactory> GetFactory();
|
|
|
-
|
|
|
- nsresult CreateInstance(const nsIID& aIID, void** aResult);
|
|
|
-
|
|
|
- size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
|
|
|
-
|
|
|
-- const nsCID mCID;
|
|
|
-+ const mozilla::Module::CIDEntry* mCIDEntry;
|
|
|
-+ nsComponentManagerImpl::KnownModule* mModule;
|
|
|
-
|
|
|
- nsCOMPtr<nsIFactory> mFactory;
|
|
|
- nsCOMPtr<nsISupports> mServiceObject;
|
|
|
- };
|
|
|
-
|
|
|
- #endif // nsComponentManager_h__
|