1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 #include "nsISupports.h"
11 #include "nsCRT.h" // for atoll
13 #include "StaticComponents.h"
15 #include "nsCategoryManager.h"
17 #include "nsComponentManager.h"
18 #include "nsDirectoryService.h"
19 #include "nsDirectoryServiceDefs.h"
20 #include "nsCategoryManager.h"
21 #include "nsLayoutModule.h"
22 #include "mozilla/MemoryReporting.h"
23 #include "nsIObserverService.h"
24 #include "nsIStringEnumerator.h"
26 #include "nsXPCOMPrivate.h"
27 #include "nsISupportsPrimitives.h"
28 #include "nsLocalFile.h"
29 #include "nsReadableUtils.h"
32 #include "nsThreadManager.h"
33 #include "nsThreadUtils.h"
35 #include "private/pprthred.h"
38 #include "ManifestParser.h"
39 #include "nsNetUtil.h"
40 #include "mozilla/Services.h"
42 #include "mozilla/GenericFactory.h"
43 #include "nsSupportsPrimitives.h"
45 #include "nsIMutableArray.h"
46 #include "mozilla/DebugOnly.h"
47 #include "mozilla/FileUtils.h"
48 #include "mozilla/ProfilerLabels.h"
49 #include "mozilla/ProfilerMarkers.h"
50 #include "mozilla/ScopeExit.h"
51 #include "mozilla/URLPreloader.h"
52 #include "mozilla/UniquePtr.h"
53 #include "mozilla/Variant.h"
55 #include <new> // for placement new
57 #include "mozilla/Omnijar.h"
59 #include "mozilla/Logging.h"
60 #include "LogModulePrefWatcher.h"
63 # include "mozmemory.h"
66 using namespace mozilla
;
67 using namespace mozilla::xpcom
;
69 static LazyLogModule
nsComponentManagerLog("nsComponentManager");
72 # define SHOW_DENIED_ON_SHUTDOWN
73 # define SHOW_CI_ON_EXISTING_SERVICE
78 class AutoIDString
: public nsAutoCStringN
<NSID_LENGTH
> {
80 explicit AutoIDString(const nsID
& aID
) {
81 SetLength(NSID_LENGTH
- 1);
83 *reinterpret_cast<char(*)[NSID_LENGTH
]>(BeginWriting()));
92 using ProcessSelector
= Module::ProcessSelector
;
94 // Note: These must be kept in sync with the ProcessSelector definition in
96 bool ProcessSelectorMatches(ProcessSelector aSelector
) {
97 GeckoProcessType type
= XRE_GetProcessType();
98 if (type
== GeckoProcessType_GPU
) {
99 return !!(aSelector
& Module::ALLOW_IN_GPU_PROCESS
);
102 if (type
== GeckoProcessType_RDD
) {
103 return !!(aSelector
& Module::ALLOW_IN_RDD_PROCESS
);
106 if (type
== GeckoProcessType_Socket
) {
107 return !!(aSelector
& (Module::ALLOW_IN_SOCKET_PROCESS
));
110 if (type
== GeckoProcessType_VR
) {
111 return !!(aSelector
& Module::ALLOW_IN_VR_PROCESS
);
114 if (type
== GeckoProcessType_Utility
) {
115 return !!(aSelector
& Module::ALLOW_IN_UTILITY_PROCESS
);
118 if (type
== GeckoProcessType_GMPlugin
) {
119 return !!(aSelector
& Module::ALLOW_IN_GMPLUGIN_PROCESS
);
122 // Only allow XPCOM modules which can be loaded in all processes to be loaded
123 // in the IPDLUnitTest process.
124 if (type
== GeckoProcessType_IPDLUnitTest
) {
125 return size_t(aSelector
) == Module::kMaxProcessSelector
;
128 if (aSelector
& Module::MAIN_PROCESS_ONLY
) {
129 return type
== GeckoProcessType_Default
;
131 if (aSelector
& Module::CONTENT_PROCESS_ONLY
) {
132 return type
== GeckoProcessType_Content
;
137 static bool gProcessMatchTable
[Module::kMaxProcessSelector
+ 1];
139 bool FastProcessSelectorMatches(ProcessSelector aSelector
) {
140 return gProcessMatchTable
[size_t(aSelector
)];
144 } // namespace mozilla
149 * A wrapper simple wrapper class, which can hold either a dynamic
150 * nsFactoryEntry instance, or a static StaticModule entry, and transparently
151 * forwards method calls to the wrapped object.
153 * This allows the same code to work with either static or dynamic modules
154 * without caring about the difference.
156 class MOZ_STACK_CLASS EntryWrapper final
{
158 explicit EntryWrapper(nsFactoryEntry
* aEntry
) : mEntry(aEntry
) {}
160 explicit EntryWrapper(const StaticModule
* aEntry
) : mEntry(aEntry
) {}
162 #define MATCH(type, ifFactory, ifStatic) \
164 type operator()(nsFactoryEntry* entry) { ifFactory; } \
165 type operator()(const StaticModule* entry) { ifStatic; } \
167 return mEntry.match((Matcher()))
170 MATCH(const nsID
&, return entry
->mCID
, return entry
->CID());
173 already_AddRefed
<nsIFactory
> GetFactory() {
174 MATCH(already_AddRefed
<nsIFactory
>, return entry
->GetFactory(),
175 return entry
->GetFactory());
179 * Creates an instance of the underlying component. This should be used in
180 * preference to GetFactory()->CreateInstance() where appropriate, since it
181 * side-steps the necessity of creating a nsIFactory instance for static
184 nsresult
CreateInstance(const nsIID
& aIID
, void** aResult
) {
185 if (mEntry
.is
<nsFactoryEntry
*>()) {
186 return mEntry
.as
<nsFactoryEntry
*>()->CreateInstance(aIID
, aResult
);
188 return mEntry
.as
<const StaticModule
*>()->CreateInstance(aIID
, aResult
);
192 * Returns the cached service instance for this entry, if any. This should
193 * only be accessed while mLock is held.
195 nsISupports
* ServiceInstance() {
196 MATCH(nsISupports
*, return entry
->mServiceObject
,
197 return entry
->ServiceInstance());
199 void SetServiceInstance(already_AddRefed
<nsISupports
> aInst
) {
200 if (mEntry
.is
<nsFactoryEntry
*>()) {
201 mEntry
.as
<nsFactoryEntry
*>()->mServiceObject
= aInst
;
203 return mEntry
.as
<const StaticModule
*>()->SetServiceInstance(
209 * Returns the description string for the module this entry belongs to.
210 * Currently always returns "<unknown module>".
212 nsCString
ModuleDescription() { return "<unknown module>"_ns
; }
215 Variant
<nsFactoryEntry
*, const StaticModule
*> mEntry
;
220 // this is safe to call during InitXPCOM
221 static already_AddRefed
<nsIFile
> GetLocationFromDirectoryService(
223 nsCOMPtr
<nsIProperties
> directoryService
;
224 nsDirectoryService::Create(NS_GET_IID(nsIProperties
),
225 getter_AddRefs(directoryService
));
227 if (!directoryService
) {
231 nsCOMPtr
<nsIFile
> file
;
233 directoryService
->Get(aProp
, NS_GET_IID(nsIFile
), getter_AddRefs(file
));
238 return file
.forget();
241 static already_AddRefed
<nsIFile
> CloneAndAppend(nsIFile
* aBase
,
242 const nsACString
& aAppend
) {
244 aBase
->Clone(getter_AddRefs(f
));
249 f
->AppendNative(aAppend
);
253 ////////////////////////////////////////////////////////////////////////////////
254 // nsComponentManagerImpl
255 ////////////////////////////////////////////////////////////////////////////////
257 nsresult
nsComponentManagerImpl::Create(REFNSIID aIID
, void** aResult
) {
258 if (!gComponentManager
) {
259 return NS_ERROR_FAILURE
;
262 return gComponentManager
->QueryInterface(aIID
, aResult
);
265 static const int CONTRACTID_HASHTABLE_INITIAL_LENGTH
= 8;
267 nsComponentManagerImpl::nsComponentManagerImpl()
268 : mFactories(CONTRACTID_HASHTABLE_INITIAL_LENGTH
),
269 mContractIDs(CONTRACTID_HASHTABLE_INITIAL_LENGTH
),
270 mLock("nsComponentManagerImpl.mLock"),
271 mStatus(NOT_INITIALIZED
) {}
273 nsTArray
<nsComponentManagerImpl::ComponentLocation
>*
274 nsComponentManagerImpl::sModuleLocations
;
277 void nsComponentManagerImpl::InitializeModuleLocations() {
278 if (sModuleLocations
) {
282 sModuleLocations
= new nsTArray
<ComponentLocation
>;
285 nsresult
nsComponentManagerImpl::Init() {
287 gProcessMatchTable
[size_t(ProcessSelector::ANY_PROCESS
)] =
288 ProcessSelectorMatches(ProcessSelector::ANY_PROCESS
);
289 gProcessMatchTable
[size_t(ProcessSelector::MAIN_PROCESS_ONLY
)] =
290 ProcessSelectorMatches(ProcessSelector::MAIN_PROCESS_ONLY
);
291 gProcessMatchTable
[size_t(ProcessSelector::CONTENT_PROCESS_ONLY
)] =
292 ProcessSelectorMatches(ProcessSelector::CONTENT_PROCESS_ONLY
);
293 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_GPU_PROCESS
)] =
294 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_PROCESS
);
295 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_VR_PROCESS
)] =
296 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_VR_PROCESS
);
297 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_SOCKET_PROCESS
)] =
298 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_SOCKET_PROCESS
);
299 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_RDD_PROCESS
)] =
300 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_RDD_PROCESS
);
301 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_GMPLUGIN_PROCESS
)] =
302 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GMPLUGIN_PROCESS
);
303 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_GPU_AND_MAIN_PROCESS
)] =
304 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_AND_MAIN_PROCESS
);
305 gProcessMatchTable
[size_t(ProcessSelector::ALLOW_IN_GPU_AND_VR_PROCESS
)] =
306 ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_AND_VR_PROCESS
);
307 gProcessMatchTable
[size_t(
308 ProcessSelector::ALLOW_IN_GPU_AND_SOCKET_PROCESS
)] =
309 ProcessSelectorMatches(
310 ProcessSelector::ALLOW_IN_GPU_AND_SOCKET_PROCESS
);
311 gProcessMatchTable
[size_t(
312 ProcessSelector::ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS
)] =
313 ProcessSelectorMatches(
314 ProcessSelector::ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS
);
315 gProcessMatchTable
[size_t(
316 ProcessSelector::ALLOW_IN_RDD_AND_SOCKET_PROCESS
)] =
317 ProcessSelectorMatches(
318 ProcessSelector::ALLOW_IN_RDD_AND_SOCKET_PROCESS
);
319 gProcessMatchTable
[size_t(
320 ProcessSelector::ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS
)] =
321 ProcessSelectorMatches(
322 ProcessSelector::ALLOW_IN_GPU_RDD_AND_SOCKET_PROCESS
);
323 gProcessMatchTable
[size_t(
324 ProcessSelector::ALLOW_IN_GPU_RDD_SOCKET_AND_UTILITY_PROCESS
)] =
325 ProcessSelectorMatches(
326 ProcessSelector::ALLOW_IN_GPU_RDD_SOCKET_AND_UTILITY_PROCESS
);
327 gProcessMatchTable
[size_t(
328 ProcessSelector::ALLOW_IN_GPU_RDD_VR_AND_SOCKET_PROCESS
)] =
329 ProcessSelectorMatches(
330 ProcessSelector::ALLOW_IN_GPU_RDD_VR_AND_SOCKET_PROCESS
);
331 gProcessMatchTable
[size_t(
332 ProcessSelector::ALLOW_IN_GPU_RDD_VR_SOCKET_AND_UTILITY_PROCESS
)] =
333 ProcessSelectorMatches(
334 ProcessSelector::ALLOW_IN_GPU_RDD_VR_SOCKET_AND_UTILITY_PROCESS
);
335 gProcessMatchTable
[size_t(
337 ALLOW_IN_GPU_RDD_VR_SOCKET_UTILITY_AND_GMPLUGIN_PROCESS
)] =
338 ProcessSelectorMatches(
340 ALLOW_IN_GPU_RDD_VR_SOCKET_UTILITY_AND_GMPLUGIN_PROCESS
);
343 MOZ_ASSERT(NOT_INITIALIZED
== mStatus
);
345 nsCOMPtr
<nsIFile
> greDir
= GetLocationFromDirectoryService(NS_GRE_DIR
);
346 nsCOMPtr
<nsIFile
> appDir
=
347 GetLocationFromDirectoryService(NS_XPCOM_CURRENT_PROCESS_DIR
);
349 nsCategoryManager::GetSingleton()->SuppressNotifications(true);
351 auto* catMan
= nsCategoryManager::GetSingleton();
352 for (const auto& cat
: gStaticCategories
) {
353 for (const auto& entry
: cat
) {
354 if (entry
.Active()) {
355 catMan
->AddCategoryEntry(cat
.Name(), entry
.Entry(), entry
.Value());
360 bool loadChromeManifests
;
361 switch (XRE_GetProcessType()) {
362 // We are going to assume that only a select few (see below) process types
363 // want to load chrome manifests, and that any new process types will not
364 // want to load them, because they're not going to be executing JS.
365 case GeckoProcessType_RemoteSandboxBroker
:
367 loadChromeManifests
= false;
370 // XXX The check this code replaced implicitly let through all of these
371 // process types, but presumably only the default (parent) and content
372 // processes really need chrome manifests...?
373 case GeckoProcessType_Default
:
374 case GeckoProcessType_Content
:
375 loadChromeManifests
= true;
379 if (loadChromeManifests
) {
380 // This needs to be called very early, before anything in nsLayoutModule is
381 // used, and before any calls are made into the JS engine.
382 nsLayoutModuleInitialize();
384 mJSLoaderReady
= true;
386 // The overall order in which chrome.manifests are expected to be treated
388 // - greDir's omni.ja or greDir
389 // - appDir's omni.ja or appDir
391 InitializeModuleLocations();
392 ComponentLocation
* cl
= sModuleLocations
->AppendElement();
393 cl
->type
= NS_APP_LOCATION
;
394 RefPtr
<nsZipArchive
> greOmnijar
=
395 mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE
);
397 cl
->location
.Init(greOmnijar
, "chrome.manifest");
399 nsCOMPtr
<nsIFile
> lf
= CloneAndAppend(greDir
, "chrome.manifest"_ns
);
400 cl
->location
.Init(lf
);
403 RefPtr
<nsZipArchive
> appOmnijar
=
404 mozilla::Omnijar::GetReader(mozilla::Omnijar::APP
);
406 cl
= sModuleLocations
->AppendElement();
407 cl
->type
= NS_APP_LOCATION
;
408 cl
->location
.Init(appOmnijar
, "chrome.manifest");
411 appDir
->Equals(greDir
, &equals
);
413 cl
= sModuleLocations
->AppendElement();
414 cl
->type
= NS_APP_LOCATION
;
415 nsCOMPtr
<nsIFile
> lf
= CloneAndAppend(appDir
, "chrome.manifest"_ns
);
416 cl
->location
.Init(lf
);
420 RereadChromeManifests(false);
423 nsCategoryManager::GetSingleton()->SuppressNotifications(false);
425 RegisterWeakMemoryReporter(this);
427 // NB: The logging preference watcher needs to be registered late enough in
428 // startup that it's okay to use the preference system, but also as soon as
429 // possible so that log modules enabled via preferences are turned on as
430 // early as possible.
432 // We can't initialize the preference watcher when the log module manager is
433 // initialized, as a number of things attempt to start logging before the
434 // preference system is initialized.
436 // The preference system is registered as a component so at this point during
437 // component manager initialization we know it is setup and we can register
438 // for notifications.
439 LogModulePrefWatcher::RegisterPrefWatcher();
441 // Unfortunately, we can't register the nsCategoryManager memory reporter
442 // in its constructor (which is triggered by the GetSingleton() call
443 // above) because the memory reporter manager isn't initialized at that
444 // point. So we wait until now.
445 nsCategoryManager::GetSingleton()->InitMemoryReporter();
447 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
448 ("nsComponentManager: Initialized."));
452 MOZ_ASSERT(!XRE_IsContentProcess() ||
453 CONTRACTID_HASHTABLE_INITIAL_LENGTH
<= 8 ||
454 mFactories
.Count() > CONTRACTID_HASHTABLE_INITIAL_LENGTH
/ 3,
455 "Initial component hashtable size is too large");
460 template <typename T
>
461 static void AssertNotMallocAllocated(T
* aPtr
) {
462 #if defined(DEBUG) && defined(MOZ_MEMORY)
463 jemalloc_ptr_info_t info
;
464 jemalloc_ptr_info((void*)aPtr
, &info
);
465 MOZ_ASSERT(info
.tag
== TagUnknown
);
469 template <typename T
>
470 static void AssertNotStackAllocated(T
* aPtr
) {
471 // On all of our supported platforms, the stack grows down. Any address
472 // located below the address of our argument is therefore guaranteed not to be
473 // stack-allocated by the caller.
475 // For addresses above our argument, things get trickier. The main thread
476 // stack is traditionally placed at the top of the program's address space,
477 // but that is becoming less reliable as more and more systems adopt address
478 // space layout randomization strategies, so we have to guess how much space
479 // above our argument pointer we need to care about.
481 // On most systems, we're guaranteed at least several KiB at the top of each
482 // stack for TLS. We'd probably be safe assuming at least 4KiB in the stack
483 // segment above our argument address, but safer is... well, safer.
485 // For threads with huge stacks, it's theoretically possible that we could
486 // wind up being passed a stack-allocated string from farther up the stack,
487 // but this is a best-effort thing, so we'll assume we only care about the
488 // immediate caller. For that case, max 2KiB per stack frame is probably a
489 // reasonable guess most of the time, and is less than the ~4KiB that we
490 // expect for TLS, so go with that to avoid the risk of bumping into heap
491 // data just above the stack.
493 static constexpr size_t kFuzz
= 2048;
495 MOZ_ASSERT(uintptr_t(aPtr
) < uintptr_t(&aPtr
) ||
496 uintptr_t(aPtr
) > uintptr_t(&aPtr
) + kFuzz
);
500 static void DoRegisterManifest(NSLocationType aType
, FileLocation
& aFile
,
502 auto result
= URLPreloader::Read(aFile
);
504 nsCString
buf(result
.unwrap());
505 ParseManifest(aType
, aFile
, buf
.BeginWriting(), aChromeOnly
);
506 } else if (NS_BOOTSTRAPPED_LOCATION
!= aType
) {
508 aFile
.GetURIString(uri
);
509 LogMessage("Could not read chrome manifest '%s'.", uri
.get());
513 void nsComponentManagerImpl::RegisterManifest(NSLocationType aType
,
516 DoRegisterManifest(aType
, aFile
, aChromeOnly
);
519 void nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext
& aCx
,
520 int aLineNo
, char* const* aArgv
) {
521 char* file
= aArgv
[0];
522 FileLocation
f(aCx
.mFile
, file
);
523 RegisterManifest(aCx
.mType
, f
, aCx
.mChromeOnly
);
526 void nsComponentManagerImpl::ManifestCategory(ManifestProcessingContext
& aCx
,
527 int aLineNo
, char* const* aArgv
) {
528 char* category
= aArgv
[0];
529 char* key
= aArgv
[1];
530 char* value
= aArgv
[2];
532 nsCategoryManager::GetSingleton()->AddCategoryEntry(
533 nsDependentCString(category
), nsDependentCString(key
),
534 nsDependentCString(value
));
537 void nsComponentManagerImpl::RereadChromeManifests(bool aChromeOnly
) {
538 for (uint32_t i
= 0; i
< sModuleLocations
->Length(); ++i
) {
539 ComponentLocation
& l
= sModuleLocations
->ElementAt(i
);
540 RegisterManifest(l
.type
, l
.location
, aChromeOnly
);
543 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
545 obs
->NotifyObservers(nullptr, "chrome-manifests-loaded", nullptr);
549 nsresult
nsComponentManagerImpl::Shutdown(void) {
550 MOZ_ASSERT(NORMAL
== mStatus
);
552 mStatus
= SHUTDOWN_IN_PROGRESS
;
554 // Shutdown the component manager
555 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
556 ("nsComponentManager: Beginning Shutdown."));
558 UnregisterWeakMemoryReporter(this);
560 // Release all cached factories
561 mContractIDs
.Clear();
562 mFactories
.Clear(); // XXX release the objects, don't just clear
564 StaticComponents::Shutdown();
566 delete sModuleLocations
;
568 mStatus
= SHUTDOWN_COMPLETE
;
570 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
571 ("nsComponentManager: Shutdown complete."));
576 nsComponentManagerImpl::~nsComponentManagerImpl() {
577 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
578 ("nsComponentManager: Beginning destruction."));
580 if (SHUTDOWN_COMPLETE
!= mStatus
) {
584 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
585 ("nsComponentManager: Destroyed."));
588 NS_IMPL_ISUPPORTS(nsComponentManagerImpl
, nsIComponentManager
,
589 nsIServiceManager
, nsIComponentRegistrar
,
590 nsISupportsWeakReference
, nsIInterfaceRequestor
,
593 nsresult
nsComponentManagerImpl::GetInterface(const nsIID
& aUuid
,
595 NS_WARNING("This isn't supported");
596 // fall through to QI as anything QIable is a superset of what can be
597 // got via the GetInterface()
598 return QueryInterface(aUuid
, aResult
);
601 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByCID(const nsID
& aCID
) {
602 return LookupByCID(MonitorAutoLock(mLock
), aCID
);
605 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByCID(const MonitorAutoLock
&,
607 if (const StaticModule
* module
= StaticComponents::LookupByCID(aCID
)) {
608 return Some(EntryWrapper(module
));
610 if (nsFactoryEntry
* entry
= mFactories
.Get(&aCID
)) {
611 return Some(EntryWrapper(entry
));
616 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByContractID(
617 const nsACString
& aContractID
) {
618 return LookupByContractID(MonitorAutoLock(mLock
), aContractID
);
621 Maybe
<EntryWrapper
> nsComponentManagerImpl::LookupByContractID(
622 const MonitorAutoLock
&, const nsACString
& aContractID
) {
623 if (const StaticModule
* module
=
624 StaticComponents::LookupByContractID(aContractID
)) {
625 return Some(EntryWrapper(module
));
627 if (nsFactoryEntry
* entry
= mContractIDs
.Get(aContractID
)) {
628 // UnregisterFactory might have left a stale nsFactoryEntry in
629 // mContractIDs, so we should check to see whether this entry has
631 if (entry
->mFactory
|| entry
->mServiceObject
) {
632 return Some(EntryWrapper(entry
));
638 already_AddRefed
<nsIFactory
> nsComponentManagerImpl::FindFactory(
639 const nsCID
& aClass
) {
640 Maybe
<EntryWrapper
> e
= LookupByCID(aClass
);
645 return e
->GetFactory();
648 already_AddRefed
<nsIFactory
> nsComponentManagerImpl::FindFactory(
649 const char* aContractID
, uint32_t aContractIDLen
) {
650 Maybe
<EntryWrapper
> entry
=
651 LookupByContractID(nsDependentCString(aContractID
, aContractIDLen
));
656 return entry
->GetFactory();
662 * Given a classID, this finds the singleton ClassObject that implements the
663 * CID. Returns an interface of type aIID off the singleton classobject.
666 nsComponentManagerImpl::GetClassObject(const nsCID
& aClass
, const nsIID
& aIID
,
670 if (MOZ_LOG_TEST(nsComponentManagerLog
, LogLevel::Debug
)) {
671 char buf
[NSID_LENGTH
];
672 aClass
.ToProvidedString(buf
);
673 PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf
);
676 MOZ_ASSERT(aResult
!= nullptr);
678 nsCOMPtr
<nsIFactory
> factory
= FindFactory(aClass
);
680 return NS_ERROR_FACTORY_NOT_REGISTERED
;
683 rv
= factory
->QueryInterface(aIID
, aResult
);
686 nsComponentManagerLog
, LogLevel::Warning
,
687 ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
693 nsComponentManagerImpl::GetClassObjectByContractID(const char* aContractID
,
696 if (NS_WARN_IF(!aResult
) || NS_WARN_IF(!aContractID
)) {
697 return NS_ERROR_INVALID_ARG
;
702 MOZ_LOG(nsComponentManagerLog
, LogLevel::Debug
,
703 ("nsComponentManager: GetClassObjectByContractID(%s)", aContractID
));
705 nsCOMPtr
<nsIFactory
> factory
= FindFactory(aContractID
, strlen(aContractID
));
707 return NS_ERROR_FACTORY_NOT_REGISTERED
;
710 rv
= factory
->QueryInterface(aIID
, aResult
);
712 MOZ_LOG(nsComponentManagerLog
, LogLevel::Warning
,
713 ("\t\tGetClassObjectByContractID() %s",
714 NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
722 * Create an instance of an object that implements an interface and belongs
723 * to the implementation aClass using the factory. The factory is immediately
724 * released and not held onto for any longer.
727 nsComponentManagerImpl::CreateInstance(const nsCID
& aClass
, const nsIID
& aIID
,
729 // test this first, since there's no point in creating a component during
730 // shutdown -- whether it's available or not would depend on the order it
731 // occurs in the list
732 if (gXPCOMShuttingDown
) {
733 // When processing shutdown, don't process new GetService() requests
734 #ifdef SHOW_DENIED_ON_SHUTDOWN
736 "Creating new instance on shutdown. Denied.\n"
737 " CID: %s\n IID: %s\n",
738 AutoIDString(aClass
).get(), AutoIDString(aIID
).get());
739 #endif /* SHOW_DENIED_ON_SHUTDOWN */
740 return NS_ERROR_UNEXPECTED
;
744 return NS_ERROR_NULL_POINTER
;
748 Maybe
<EntryWrapper
> entry
= LookupByCID(aClass
);
751 return NS_ERROR_FACTORY_NOT_REGISTERED
;
754 #ifdef SHOW_CI_ON_EXISTING_SERVICE
755 if (entry
->ServiceInstance()) {
756 nsAutoCString message
;
757 message
= "You are calling CreateInstance \""_ns
+ AutoIDString(aClass
) +
758 "\" when a service for this CID already exists!"_ns
;
759 NS_ERROR(message
.get());
764 nsCOMPtr
<nsIFactory
> factory
= entry
->GetFactory();
766 rv
= factory
->CreateInstance(aIID
, aResult
);
767 if (NS_SUCCEEDED(rv
) && !*aResult
) {
768 NS_ERROR("Factory did not return an object but returned success!");
769 rv
= NS_ERROR_SERVICE_NOT_AVAILABLE
;
772 // Translate error values
773 rv
= NS_ERROR_FACTORY_NOT_REGISTERED
;
776 if (MOZ_LOG_TEST(nsComponentManagerLog
, LogLevel::Warning
)) {
777 char buf
[NSID_LENGTH
];
778 aClass
.ToProvidedString(buf
);
779 MOZ_LOG(nsComponentManagerLog
, LogLevel::Warning
,
780 ("nsComponentManager: CreateInstance(%s) %s", buf
,
781 NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
788 * CreateInstanceByContractID()
790 * A variant of CreateInstance() that creates an instance of the object that
791 * implements the interface aIID and whose implementation has a contractID
794 * This is only a convenience routine that turns around can calls the
795 * CreateInstance() with classid and iid.
798 nsComponentManagerImpl::CreateInstanceByContractID(const char* aContractID
,
801 if (NS_WARN_IF(!aContractID
)) {
802 return NS_ERROR_INVALID_ARG
;
805 // test this first, since there's no point in creating a component during
806 // shutdown -- whether it's available or not would depend on the order it
807 // occurs in the list
808 if (gXPCOMShuttingDown
) {
809 // When processing shutdown, don't process new GetService() requests
810 #ifdef SHOW_DENIED_ON_SHUTDOWN
812 "Creating new instance on shutdown. Denied.\n"
813 " ContractID: %s\n IID: %s\n",
814 aContractID
, AutoIDString(aIID
).get());
815 #endif /* SHOW_DENIED_ON_SHUTDOWN */
816 return NS_ERROR_UNEXPECTED
;
820 return NS_ERROR_NULL_POINTER
;
824 Maybe
<EntryWrapper
> entry
=
825 LookupByContractID(nsDependentCString(aContractID
));
828 return NS_ERROR_FACTORY_NOT_REGISTERED
;
831 #ifdef SHOW_CI_ON_EXISTING_SERVICE
832 if (entry
->ServiceInstance()) {
833 nsAutoCString message
;
835 "You are calling CreateInstance \""_ns
+
836 nsDependentCString(aContractID
) +
838 "\" when a service for this CID already exists! "
839 "Add it to abusedContracts to track down the service consumer.");
840 NS_ERROR(message
.get());
845 nsCOMPtr
<nsIFactory
> factory
= entry
->GetFactory();
847 rv
= factory
->CreateInstance(aIID
, aResult
);
848 if (NS_SUCCEEDED(rv
) && !*aResult
) {
849 NS_ERROR("Factory did not return an object but returned success!");
850 rv
= NS_ERROR_SERVICE_NOT_AVAILABLE
;
853 // Translate error values
854 rv
= NS_ERROR_FACTORY_NOT_REGISTERED
;
857 MOZ_LOG(nsComponentManagerLog
, LogLevel::Warning
,
858 ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID
,
859 NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
864 nsresult
nsComponentManagerImpl::FreeServices() {
865 NS_ASSERTION(gXPCOMShuttingDown
,
866 "Must be shutting down in order to free all services");
868 if (!gXPCOMShuttingDown
) {
869 return NS_ERROR_FAILURE
;
872 for (nsFactoryEntry
* entry
: mFactories
.Values()) {
873 entry
->mFactory
= nullptr;
874 entry
->mServiceObject
= nullptr;
877 for (const auto& module
: gStaticModules
) {
878 module
.SetServiceInstance(nullptr);
884 // This should only ever be called within the monitor!
885 nsComponentManagerImpl::PendingServiceInfo
*
886 nsComponentManagerImpl::AddPendingService(const nsCID
& aServiceCID
,
888 PendingServiceInfo
* newInfo
= mPendingServices
.AppendElement();
890 newInfo
->cid
= &aServiceCID
;
891 newInfo
->thread
= aThread
;
896 // This should only ever be called within the monitor!
897 void nsComponentManagerImpl::RemovePendingService(MonitorAutoLock
& aLock
,
898 const nsCID
& aServiceCID
) {
899 uint32_t pendingCount
= mPendingServices
.Length();
900 for (uint32_t index
= 0; index
< pendingCount
; ++index
) {
901 const PendingServiceInfo
& info
= mPendingServices
.ElementAt(index
);
902 if (info
.cid
->Equals(aServiceCID
)) {
903 mPendingServices
.RemoveElementAt(index
);
910 // This should only ever be called within the monitor!
911 PRThread
* nsComponentManagerImpl::GetPendingServiceThread(
912 const nsCID
& aServiceCID
) const {
913 uint32_t pendingCount
= mPendingServices
.Length();
914 for (uint32_t index
= 0; index
< pendingCount
; ++index
) {
915 const PendingServiceInfo
& info
= mPendingServices
.ElementAt(index
);
916 if (info
.cid
->Equals(aServiceCID
)) {
923 nsresult
nsComponentManagerImpl::GetServiceLocked(Maybe
<MonitorAutoLock
>& aLock
,
924 EntryWrapper
& aEntry
,
927 MOZ_ASSERT(aLock
.isSome());
928 if (!aLock
.isSome()) {
929 return NS_ERROR_INVALID_ARG
;
932 if (auto* service
= aEntry
.ServiceInstance()) {
934 return service
->QueryInterface(aIID
, aResult
);
937 PRThread
* currentPRThread
= PR_GetCurrentThread();
938 MOZ_ASSERT(currentPRThread
, "This should never be null!");
940 PRThread
* pendingPRThread
;
941 while ((pendingPRThread
= GetPendingServiceThread(aEntry
.CID()))) {
942 if (pendingPRThread
== currentPRThread
) {
943 NS_ERROR("Recursive GetService!");
944 return NS_ERROR_NOT_AVAILABLE
;
950 // It's still possible that the other thread failed to create the
951 // service so we're not guaranteed to have an entry or service yet.
952 if (auto* service
= aEntry
.ServiceInstance()) {
954 return service
->QueryInterface(aIID
, aResult
);
957 DebugOnly
<PendingServiceInfo
*> newInfo
=
958 AddPendingService(aEntry
.CID(), currentPRThread
);
959 NS_ASSERTION(newInfo
, "Failed to add info to the array!");
961 // We need to not be holding the service manager's lock while calling
962 // CreateInstance, because it invokes user code which could try to re-enter
963 // the service manager:
965 nsCOMPtr
<nsISupports
> service
;
966 auto cleanup
= MakeScopeExit([&]() {
967 // `service` must be released after the lock is released, so if we fail and
968 // still have a reference, release the lock before releasing it.
970 MOZ_ASSERT(aLock
.isSome());
976 mLock
.AssertCurrentThreadOwns();
978 MonitorAutoUnlock
unlock(mLock
);
979 AUTO_PROFILER_MARKER_TEXT(
980 "GetService", OTHER
, MarkerStack::Capture(),
981 nsDependentCString(nsIDToCString(aEntry
.CID()).get()));
982 rv
= aEntry
.CreateInstance(aIID
, getter_AddRefs(service
));
984 if (NS_SUCCEEDED(rv
) && !service
) {
985 NS_ERROR("Factory did not return an object but returned success");
986 return NS_ERROR_SERVICE_NOT_AVAILABLE
;
990 pendingPRThread
= GetPendingServiceThread(aEntry
.CID());
991 MOZ_ASSERT(pendingPRThread
== currentPRThread
,
992 "Pending service array has been changed!");
994 MOZ_ASSERT(aLock
.isSome());
995 RemovePendingService(*aLock
, aEntry
.CID());
1001 NS_ASSERTION(!aEntry
.ServiceInstance(),
1002 "Created two instances of a service!");
1004 aEntry
.SetServiceInstance(service
.forget());
1008 *aResult
= do_AddRef(aEntry
.ServiceInstance()).take();
1013 nsComponentManagerImpl::GetService(const nsCID
& aClass
, const nsIID
& aIID
,
1015 // test this first, since there's no point in returning a service during
1016 // shutdown -- whether it's available or not would depend on the order it
1017 // occurs in the list
1018 if (gXPCOMShuttingDown
) {
1019 // When processing shutdown, don't process new GetService() requests
1020 #ifdef SHOW_DENIED_ON_SHUTDOWN
1022 "Getting service on shutdown. Denied.\n"
1023 " CID: %s\n IID: %s\n",
1024 AutoIDString(aClass
).get(), AutoIDString(aIID
).get());
1025 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1026 return NS_ERROR_UNEXPECTED
;
1029 Maybe
<MonitorAutoLock
> lock(std::in_place
, mLock
);
1031 Maybe
<EntryWrapper
> entry
= LookupByCID(*lock
, aClass
);
1033 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1036 return GetServiceLocked(lock
, *entry
, aIID
, aResult
);
1039 nsresult
nsComponentManagerImpl::GetService(ModuleID aId
, const nsIID
& aIID
,
1041 const auto& entry
= gStaticModules
[size_t(aId
)];
1043 // test this first, since there's no point in returning a service during
1044 // shutdown -- whether it's available or not would depend on the order it
1045 // occurs in the list
1046 if (gXPCOMShuttingDown
) {
1047 // When processing shutdown, don't process new GetService() requests
1048 #ifdef SHOW_DENIED_ON_SHUTDOWN
1050 "Getting service on shutdown. Denied.\n"
1051 " CID: %s\n IID: %s\n",
1052 AutoIDString(entry
.CID()).get(), AutoIDString(aIID
).get());
1053 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1054 return NS_ERROR_UNEXPECTED
;
1057 Maybe
<MonitorAutoLock
> lock(std::in_place
, mLock
);
1059 Maybe
<EntryWrapper
> wrapper
;
1060 if (entry
.Overridable()) {
1061 // If we expect this service to be overridden by test code, we need to look
1062 // it up by contract ID every time.
1063 wrapper
= LookupByContractID(*lock
, entry
.ContractID());
1065 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1067 } else if (!entry
.Active()) {
1068 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1070 wrapper
.emplace(&entry
);
1072 return GetServiceLocked(lock
, *wrapper
, aIID
, aResult
);
1076 nsComponentManagerImpl::IsServiceInstantiated(const nsCID
& aClass
,
1079 // Now we want to get the service if we already got it. If not, we don't want
1080 // to create an instance of it. mmh!
1082 // test this first, since there's no point in returning a service during
1083 // shutdown -- whether it's available or not would depend on the order it
1084 // occurs in the list
1085 if (gXPCOMShuttingDown
) {
1086 // When processing shutdown, don't process new GetService() requests
1087 #ifdef SHOW_DENIED_ON_SHUTDOWN
1089 "Checking for service on shutdown. Denied.\n"
1090 " CID: %s\n IID: %s\n",
1091 AutoIDString(aClass
).get(), AutoIDString(aIID
).get());
1092 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1093 return NS_ERROR_UNEXPECTED
;
1096 if (Maybe
<EntryWrapper
> entry
= LookupByCID(aClass
)) {
1097 if (auto* service
= entry
->ServiceInstance()) {
1098 nsCOMPtr
<nsISupports
> instance
;
1099 nsresult rv
= service
->QueryInterface(aIID
, getter_AddRefs(instance
));
1100 *aResult
= (instance
!= nullptr);
1110 nsComponentManagerImpl::IsServiceInstantiatedByContractID(
1111 const char* aContractID
, const nsIID
& aIID
, bool* aResult
) {
1112 // Now we want to get the service if we already got it. If not, we don't want
1113 // to create an instance of it. mmh!
1115 // test this first, since there's no point in returning a service during
1116 // shutdown -- whether it's available or not would depend on the order it
1117 // occurs in the list
1118 if (gXPCOMShuttingDown
) {
1119 // When processing shutdown, don't process new GetService() requests
1120 #ifdef SHOW_DENIED_ON_SHUTDOWN
1122 "Checking for service on shutdown. Denied.\n"
1123 " ContractID: %s\n IID: %s\n",
1124 aContractID
, AutoIDString(aIID
).get());
1125 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1126 return NS_ERROR_UNEXPECTED
;
1129 if (Maybe
<EntryWrapper
> entry
=
1130 LookupByContractID(nsDependentCString(aContractID
))) {
1131 if (auto* service
= entry
->ServiceInstance()) {
1132 nsCOMPtr
<nsISupports
> instance
;
1133 nsresult rv
= service
->QueryInterface(aIID
, getter_AddRefs(instance
));
1134 *aResult
= (instance
!= nullptr);
1144 nsComponentManagerImpl::GetServiceByContractID(const char* aContractID
,
1147 // test this first, since there's no point in returning a service during
1148 // shutdown -- whether it's available or not would depend on the order it
1149 // occurs in the list
1150 if (gXPCOMShuttingDown
) {
1151 // When processing shutdown, don't process new GetService() requests
1152 #ifdef SHOW_DENIED_ON_SHUTDOWN
1154 "Getting service on shutdown. Denied.\n"
1155 " ContractID: %s\n IID: %s\n",
1156 aContractID
, AutoIDString(aIID
).get());
1157 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1158 return NS_ERROR_UNEXPECTED
;
1161 AUTO_PROFILER_LABEL_DYNAMIC_CSTR_NONSENSITIVE("GetServiceByContractID", OTHER
,
1163 Maybe
<MonitorAutoLock
> lock(std::in_place
, mLock
);
1165 Maybe
<EntryWrapper
> entry
=
1166 LookupByContractID(*lock
, nsDependentCString(aContractID
));
1168 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1171 return GetServiceLocked(lock
, *entry
, aIID
, aResult
);
1175 nsComponentManagerImpl::RegisterFactory(const nsCID
& aClass
, const char* aName
,
1176 const char* aContractID
,
1177 nsIFactory
* aFactory
) {
1179 // If a null factory is passed in, this call just wants to reset
1180 // the contract ID to point to an existing CID entry.
1182 return NS_ERROR_INVALID_ARG
;
1185 nsDependentCString
contractID(aContractID
);
1187 MonitorAutoLock
lock(mLock
);
1188 nsFactoryEntry
* oldf
= mFactories
.Get(&aClass
);
1190 StaticComponents::InvalidateContractID(contractID
);
1191 mContractIDs
.InsertOrUpdate(contractID
, oldf
);
1195 if (StaticComponents::LookupByCID(aClass
)) {
1196 // If this is the CID of a static module, just reset the invalid bit of
1197 // the static entry for this contract ID, and assume it points to the
1199 if (StaticComponents::InvalidateContractID(contractID
, false)) {
1200 mContractIDs
.Remove(contractID
);
1204 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1207 auto f
= MakeUnique
<nsFactoryEntry
>(aClass
, aFactory
);
1209 MonitorAutoLock
lock(mLock
);
1210 return mFactories
.WithEntryHandle(&f
->mCID
, [&](auto&& entry
) {
1212 return NS_ERROR_FACTORY_EXISTS
;
1214 if (StaticComponents::LookupByCID(f
->mCID
)) {
1215 return NS_ERROR_FACTORY_EXISTS
;
1218 nsDependentCString
contractID(aContractID
);
1219 mContractIDs
.InsertOrUpdate(contractID
, f
.get());
1220 // We allow dynamically-registered contract IDs to override static
1221 // entries, so invalidate any static entry for this contract ID.
1222 StaticComponents::InvalidateContractID(contractID
);
1224 entry
.Insert(f
.release());
1231 nsComponentManagerImpl::UnregisterFactory(const nsCID
& aClass
,
1232 nsIFactory
* aFactory
) {
1233 // Don't release the dying factory or service object until releasing
1234 // the component manager monitor.
1235 nsCOMPtr
<nsIFactory
> dyingFactory
;
1236 nsCOMPtr
<nsISupports
> dyingServiceObject
;
1239 MonitorAutoLock
lock(mLock
);
1240 auto entry
= mFactories
.Lookup(&aClass
);
1241 nsFactoryEntry
* f
= entry
? entry
.Data() : nullptr;
1242 if (!f
|| f
->mFactory
!= aFactory
) {
1243 // Note: We do not support unregistering static factories.
1244 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1249 // This might leave a stale contractid -> factory mapping in
1250 // place, so null out the factory entry (see
1251 // nsFactoryEntry::GetFactory)
1252 f
->mFactory
.swap(dyingFactory
);
1253 f
->mServiceObject
.swap(dyingServiceObject
);
1260 nsComponentManagerImpl::AutoRegister(nsIFile
* aLocation
) {
1261 XRE_AddManifestLocation(NS_EXTENSION_LOCATION
, aLocation
);
1266 nsComponentManagerImpl::IsCIDRegistered(const nsCID
& aClass
, bool* aResult
) {
1267 *aResult
= LookupByCID(aClass
).isSome();
1272 nsComponentManagerImpl::IsContractIDRegistered(const char* aClass
,
1274 if (NS_WARN_IF(!aClass
)) {
1275 return NS_ERROR_INVALID_ARG
;
1278 Maybe
<EntryWrapper
> entry
= LookupByContractID(nsDependentCString(aClass
));
1280 *aResult
= entry
.isSome();
1285 nsComponentManagerImpl::GetContractIDs(nsTArray
<nsCString
>& aResult
) {
1286 aResult
= ToTArray
<nsTArray
<nsCString
>>(mContractIDs
.Keys());
1288 for (const auto& entry
: gContractEntries
) {
1289 if (!entry
.Invalid()) {
1290 aResult
.AppendElement(entry
.ContractID());
1298 nsComponentManagerImpl::ContractIDToCID(const char* aContractID
,
1301 MonitorAutoLock
lock(mLock
);
1302 Maybe
<EntryWrapper
> entry
=
1303 LookupByContractID(lock
, nsDependentCString(aContractID
));
1305 *aResult
= (nsCID
*)moz_xmalloc(sizeof(nsCID
));
1306 **aResult
= entry
->CID();
1311 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1314 MOZ_DEFINE_MALLOC_SIZE_OF(ComponentManagerMallocSizeOf
)
1317 nsComponentManagerImpl::CollectReports(nsIHandleReportCallback
* aHandleReport
,
1318 nsISupports
* aData
, bool aAnonymize
) {
1319 MOZ_COLLECT_REPORT("explicit/xpcom/component-manager", KIND_HEAP
, UNITS_BYTES
,
1320 SizeOfIncludingThis(ComponentManagerMallocSizeOf
),
1321 "Memory used for the XPCOM component manager.");
1326 size_t nsComponentManagerImpl::SizeOfIncludingThis(
1327 mozilla::MallocSizeOf aMallocSizeOf
) const {
1328 size_t n
= aMallocSizeOf(this);
1330 n
+= mFactories
.ShallowSizeOfExcludingThis(aMallocSizeOf
);
1331 for (const auto& data
: mFactories
.Values()) {
1332 n
+= data
->SizeOfIncludingThis(aMallocSizeOf
);
1335 n
+= mContractIDs
.ShallowSizeOfExcludingThis(aMallocSizeOf
);
1336 for (const auto& key
: mContractIDs
.Keys()) {
1337 // We don't measure the nsFactoryEntry data because it's owned by
1338 // mFactories (which is measured above).
1339 n
+= key
.SizeOfExcludingThisIfUnshared(aMallocSizeOf
);
1342 if (sModuleLocations
) {
1343 n
+= sModuleLocations
->ShallowSizeOfIncludingThis(aMallocSizeOf
);
1346 n
+= mPendingServices
.ShallowSizeOfExcludingThis(aMallocSizeOf
);
1348 // Measurement of the following members may be added later if DMD finds it is
1351 // - sModuleLocations' entries
1356 ////////////////////////////////////////////////////////////////////////////////
1358 ////////////////////////////////////////////////////////////////////////////////
1360 nsFactoryEntry::nsFactoryEntry(const nsCID
& aCID
, nsIFactory
* aFactory
)
1361 : mCID(aCID
), mFactory(aFactory
) {}
1363 already_AddRefed
<nsIFactory
> nsFactoryEntry::GetFactory() {
1364 nsComponentManagerImpl::gComponentManager
->mLock
.AssertNotCurrentThreadOwns();
1366 nsCOMPtr
<nsIFactory
> factory
= mFactory
;
1367 return factory
.forget();
1370 nsresult
nsFactoryEntry::CreateInstance(const nsIID
& aIID
, void** aResult
) {
1371 nsCOMPtr
<nsIFactory
> factory
= GetFactory();
1372 NS_ENSURE_TRUE(factory
, NS_ERROR_FAILURE
);
1373 return factory
->CreateInstance(aIID
, aResult
);
1376 size_t nsFactoryEntry::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf
) {
1377 size_t n
= aMallocSizeOf(this);
1379 // Measurement of the following members may be added later if DMD finds it is
1383 // - mServiceObject;
1388 ////////////////////////////////////////////////////////////////////////////////
1389 // Static Access Functions
1390 ////////////////////////////////////////////////////////////////////////////////
1392 nsresult
NS_GetComponentManager(nsIComponentManager
** aResult
) {
1393 if (!nsComponentManagerImpl::gComponentManager
) {
1394 return NS_ERROR_NOT_INITIALIZED
;
1397 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1401 nsresult
NS_GetServiceManager(nsIServiceManager
** aResult
) {
1402 if (!nsComponentManagerImpl::gComponentManager
) {
1403 return NS_ERROR_NOT_INITIALIZED
;
1406 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1410 nsresult
NS_GetComponentRegistrar(nsIComponentRegistrar
** aResult
) {
1411 if (!nsComponentManagerImpl::gComponentManager
) {
1412 return NS_ERROR_NOT_INITIALIZED
;
1415 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1420 nsComponentManagerImpl::AddBootstrappedManifestLocation(nsIFile
* aLocation
) {
1421 NS_ENSURE_ARG_POINTER(aLocation
);
1424 nsresult rv
= aLocation
->GetPath(path
);
1425 if (NS_FAILED(rv
)) {
1429 if (Substring(path
, path
.Length() - 4).EqualsLiteral(".xpi")) {
1430 return XRE_AddJarManifestLocation(NS_BOOTSTRAPPED_LOCATION
, aLocation
);
1433 nsCOMPtr
<nsIFile
> manifest
= CloneAndAppend(aLocation
, "chrome.manifest"_ns
);
1434 return XRE_AddManifestLocation(NS_BOOTSTRAPPED_LOCATION
, manifest
);
1438 nsComponentManagerImpl::RemoveBootstrappedManifestLocation(nsIFile
* aLocation
) {
1439 NS_ENSURE_ARG_POINTER(aLocation
);
1441 nsCOMPtr
<nsIChromeRegistry
> cr
= mozilla::services::GetChromeRegistry();
1443 return NS_ERROR_FAILURE
;
1447 nsresult rv
= aLocation
->GetPath(path
);
1448 if (NS_FAILED(rv
)) {
1452 nsComponentManagerImpl::ComponentLocation elem
;
1453 elem
.type
= NS_BOOTSTRAPPED_LOCATION
;
1455 if (Substring(path
, path
.Length() - 4).EqualsLiteral(".xpi")) {
1456 elem
.location
.Init(aLocation
, "chrome.manifest");
1458 nsCOMPtr
<nsIFile
> lf
= CloneAndAppend(aLocation
, "chrome.manifest"_ns
);
1459 elem
.location
.Init(lf
);
1462 // Remove reference.
1463 nsComponentManagerImpl::sModuleLocations
->RemoveElement(
1464 elem
, ComponentLocationComparator());
1466 rv
= cr
->CheckForNewChrome();
1471 nsComponentManagerImpl::GetComponentJSMs(nsIUTF8StringEnumerator
** aJSMs
) {
1472 nsCOMPtr
<nsIUTF8StringEnumerator
> result
=
1473 StaticComponents::GetComponentJSMs();
1474 result
.forget(aJSMs
);
1479 nsComponentManagerImpl::GetComponentESModules(
1480 nsIUTF8StringEnumerator
** aESModules
) {
1481 nsCOMPtr
<nsIUTF8StringEnumerator
> result
=
1482 StaticComponents::GetComponentESModules();
1483 result
.forget(aESModules
);
1488 nsComponentManagerImpl::GetManifestLocations(nsIArray
** aLocations
) {
1489 NS_ENSURE_ARG_POINTER(aLocations
);
1490 *aLocations
= nullptr;
1492 if (!sModuleLocations
) {
1493 return NS_ERROR_NOT_INITIALIZED
;
1496 nsCOMPtr
<nsIMutableArray
> locations
= nsArray::Create();
1498 for (uint32_t i
= 0; i
< sModuleLocations
->Length(); ++i
) {
1499 ComponentLocation
& l
= sModuleLocations
->ElementAt(i
);
1500 FileLocation loc
= l
.location
;
1501 nsCString uriString
;
1502 loc
.GetURIString(uriString
);
1503 nsCOMPtr
<nsIURI
> uri
;
1504 rv
= NS_NewURI(getter_AddRefs(uri
), uriString
);
1505 if (NS_SUCCEEDED(rv
)) {
1506 locations
->AppendElement(uri
);
1510 locations
.forget(aLocations
);
1514 EXPORT_XPCOM_API(nsresult
)
1515 XRE_AddManifestLocation(NSLocationType aType
, nsIFile
* aLocation
) {
1516 nsComponentManagerImpl::InitializeModuleLocations();
1517 nsComponentManagerImpl::ComponentLocation
* c
=
1518 nsComponentManagerImpl::sModuleLocations
->AppendElement();
1520 c
->location
.Init(aLocation
);
1522 if (nsComponentManagerImpl::gComponentManager
&&
1523 nsComponentManagerImpl::NORMAL
==
1524 nsComponentManagerImpl::gComponentManager
->mStatus
) {
1525 nsComponentManagerImpl::gComponentManager
->RegisterManifest(
1526 aType
, c
->location
, false);
1532 EXPORT_XPCOM_API(nsresult
)
1533 XRE_AddJarManifestLocation(NSLocationType aType
, nsIFile
* aLocation
) {
1534 nsComponentManagerImpl::InitializeModuleLocations();
1535 nsComponentManagerImpl::ComponentLocation
* c
=
1536 nsComponentManagerImpl::sModuleLocations
->AppendElement();
1539 c
->location
.Init(aLocation
, "chrome.manifest");
1541 if (nsComponentManagerImpl::gComponentManager
&&
1542 nsComponentManagerImpl::NORMAL
==
1543 nsComponentManagerImpl::gComponentManager
->mStatus
) {
1544 nsComponentManagerImpl::gComponentManager
->RegisterManifest(
1545 aType
, c
->location
, false);
1551 // Expose some important global interfaces to rust for the rust xpcom API. These
1552 // methods return a non-owning reference to the component manager, which should
1553 // live for the lifetime of XPCOM.
1556 const nsIComponentManager
* Gecko_GetComponentManager() {
1557 return nsComponentManagerImpl::gComponentManager
;
1560 const nsIServiceManager
* Gecko_GetServiceManager() {
1561 return nsComponentManagerImpl::gComponentManager
;
1564 const nsIComponentRegistrar
* Gecko_GetComponentRegistrar() {
1565 return nsComponentManagerImpl::gComponentManager
;
1568 // FFI-compatible version of `GetServiceHelper::operator()`.
1569 nsresult
Gecko_GetServiceByModuleID(ModuleID aId
, const nsIID
* aIID
,
1571 return nsComponentManagerImpl::gComponentManager
->GetService(aId
, *aIID
,
1575 // FFI-compatible version of `CreateInstanceHelper::operator()`.
1576 nsresult
Gecko_CreateInstanceByModuleID(ModuleID aId
, const nsIID
* aIID
,
1578 const auto& entry
= gStaticModules
[size_t(aId
)];
1579 if (!entry
.Active()) {
1580 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1583 nsresult rv
= entry
.CreateInstance(*aIID
, aResult
);