1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set ts=8 sts=4 et sw=4 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/.
7 * This Original Code has been modified by IBM Corporation.
8 * Modifications made by IBM described herein are
9 * Copyright (c) International Business Machines
12 * Modifications to Mozilla code or documentation
13 * identified per MPL Section 3.3
15 * Date Modified by Description of modification
16 * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
21 #include "nsISupports.h"
23 #include "nsCRT.h" // for atoll
25 // Arena used by component manager for storing contractid string, dll
26 // location strings and small objects
27 // CAUTION: Arena align mask needs to be defined before including plarena.h
28 // currently from nsComponentManager.h
29 #define PL_ARENA_CONST_ALIGN_MASK 7
30 #define NS_CM_BLOCK_SIZE (1024 * 8)
32 #include "nsCategoryManager.h"
34 #include "nsComponentManager.h"
35 #include "nsDirectoryService.h"
36 #include "nsDirectoryServiceDefs.h"
37 #include "nsCategoryManager.h"
38 #include "nsCategoryManagerUtils.h"
39 #include "xptiprivate.h"
40 #include "mozilla/MemoryReporting.h"
41 #include "mozilla/XPTInterfaceInfoManager.h"
42 #include "nsIConsoleService.h"
43 #include "nsIObserverService.h"
44 #include "nsISimpleEnumerator.h"
45 #include "nsIStringEnumerator.h"
47 #include "nsXPCOMPrivate.h"
48 #include "nsISupportsPrimitives.h"
49 #include "nsIClassInfo.h"
50 #include "nsLocalFile.h"
51 #include "nsReadableUtils.h"
53 #include "nsXPIDLString.h"
55 #include "xptinfo.h" // this after nsISupports, to pick up IID so that xpt stuff doesn't try to define it itself...
56 #include "nsThreadUtils.h"
58 #include "private/pprthred.h"
61 #include "ManifestParser.h"
62 #include "mozilla/Services.h"
64 #include "mozilla/GenericFactory.h"
65 #include "nsSupportsPrimitives.h"
67 #include "nsIMutableArray.h"
68 #include "nsArrayEnumerator.h"
69 #include "nsStringEnumerator.h"
70 #include "mozilla/FileUtils.h"
71 #include "nsNetUtil.h"
72 #include "nsDataHashtable.h"
74 #include <new> // for placement new
76 #include "mozilla/Omnijar.h"
80 using namespace mozilla
;
82 PRLogModuleInfo
* nsComponentManagerLog
= nullptr;
84 #if 0 || defined (DEBUG_timeless)
85 #define SHOW_DENIED_ON_SHUTDOWN
86 #define SHOW_CI_ON_EXISTING_SERVICE
89 // Bloated registry buffer size to improve startup performance -- needs to
90 // be big enough to fit the entire file into memory or it'll thrash.
91 // 512K is big enough to allow for some future growth in the registry.
92 #define BIG_REGISTRY_BUFLEN (512*1024)
95 const char xpcomComponentsKeyName
[] = "software/mozilla/XPCOM/components";
96 const char xpcomKeyName
[] = "software/mozilla/XPCOM";
99 const char fileSizeValueName
[] = "FileSize";
100 const char lastModValueName
[] = "LastModTimeStamp";
101 const char nativeComponentType
[] = "application/x-mozilla-native";
102 const char staticComponentType
[] = "application/x-mozilla-static";
104 NS_DEFINE_CID(kCategoryManagerCID
, NS_CATEGORYMANAGER_CID
);
106 #define UID_STRING_LENGTH 39
108 #ifdef MOZ_B2G_LOADER
109 typedef nsDataHashtable
<nsCStringHashKey
, bool> XPTIInfosBookType
;
110 static XPTIInfosBookType
* sXPTIInfosBook
= nullptr;
112 static XPTIInfosBookType
*
115 if (!sXPTIInfosBook
) {
116 sXPTIInfosBook
= new XPTIInfosBookType
;
118 return sXPTIInfosBook
;
122 IsRegisteredXPTIInfo(FileLocation
& aFile
)
125 aFile
.GetURIString(uri
);
126 return GetXPTIInfosBook()->Get(uri
);
130 MarkRegisteredXPTIInfo(FileLocation
& aFile
)
133 aFile
.GetURIString(uri
);
134 GetXPTIInfosBook()->Put(uri
, true);
136 #endif /* MOZ_B2G_LOADER */
139 nsGetServiceFromCategory::operator()(const nsIID
& aIID
,
140 void** aInstancePtr
) const
143 nsXPIDLCString value
;
144 nsCOMPtr
<nsICategoryManager
> catman
;
145 nsComponentManagerImpl
* compMgr
= nsComponentManagerImpl::gComponentManager
;
147 rv
= NS_ERROR_NOT_INITIALIZED
;
151 if (!mCategory
|| !mEntry
) {
152 // when categories have defaults, use that for null mEntry
153 rv
= NS_ERROR_NULL_POINTER
;
157 rv
= compMgr
->nsComponentManagerImpl::GetService(kCategoryManagerCID
,
158 NS_GET_IID(nsICategoryManager
),
159 getter_AddRefs(catman
));
164 /* find the contractID for category.entry */
165 rv
= catman
->GetCategoryEntry(mCategory
, mEntry
,
166 getter_Copies(value
));
171 rv
= NS_ERROR_SERVICE_NOT_AVAILABLE
;
175 rv
= compMgr
->nsComponentManagerImpl::GetServiceByContractID(value
,
188 ////////////////////////////////////////////////////////////////////////////////
189 // Arena helper functions
190 ////////////////////////////////////////////////////////////////////////////////
192 ArenaStrndup(const char* aStr
, uint32_t aLen
, PLArenaPool
* aArena
)
195 // Include trailing null in the aLen
196 PL_ARENA_ALLOCATE(mem
, aArena
, aLen
+ 1);
198 memcpy(mem
, aStr
, aLen
+ 1);
200 return static_cast<char*>(mem
);
204 ArenaStrdup(const char* aStr
, PLArenaPool
* aArena
)
206 return ArenaStrndup(aStr
, strlen(aStr
), aArena
);
209 // GetService and a few other functions need to exit their mutex mid-function
210 // without reentering it later in the block. This class supports that
211 // style of early-exit that MutexAutoUnlock doesn't.
215 class MOZ_STACK_CLASS MutexLock
218 explicit MutexLock(SafeMutex
& aMutex
)
234 NS_ASSERTION(!mLocked
, "Re-entering a mutex");
241 NS_ASSERTION(mLocked
, "Exiting a mutex that isn't held!");
251 } // anonymous namespace
253 // this is safe to call during InitXPCOM
254 static already_AddRefed
<nsIFile
>
255 GetLocationFromDirectoryService(const char* aProp
)
257 nsCOMPtr
<nsIProperties
> directoryService
;
258 nsDirectoryService::Create(nullptr,
259 NS_GET_IID(nsIProperties
),
260 getter_AddRefs(directoryService
));
262 if (!directoryService
) {
266 nsCOMPtr
<nsIFile
> file
;
267 nsresult rv
= directoryService
->Get(aProp
,
269 getter_AddRefs(file
));
274 return file
.forget();
277 static already_AddRefed
<nsIFile
>
278 CloneAndAppend(nsIFile
* aBase
, const nsACString
& aAppend
)
281 aBase
->Clone(getter_AddRefs(f
));
286 f
->AppendNative(aAppend
);
290 ////////////////////////////////////////////////////////////////////////////////
291 // nsComponentManagerImpl
292 ////////////////////////////////////////////////////////////////////////////////
295 nsComponentManagerImpl::Create(nsISupports
* aOuter
, REFNSIID aIID
,
299 return NS_ERROR_NO_AGGREGATION
;
302 if (!gComponentManager
) {
303 return NS_ERROR_FAILURE
;
306 return gComponentManager
->QueryInterface(aIID
, aResult
);
309 static const int CONTRACTID_HASHTABLE_INITIAL_LENGTH
= 1024;
311 nsComponentManagerImpl::nsComponentManagerImpl()
312 : mFactories(CONTRACTID_HASHTABLE_INITIAL_LENGTH
)
313 , mContractIDs(CONTRACTID_HASHTABLE_INITIAL_LENGTH
)
314 , mLock("nsComponentManagerImpl.mLock")
315 , mStatus(NOT_INITIALIZED
)
319 nsTArray
<const mozilla::Module
*>* nsComponentManagerImpl::sStaticModules
;
321 NSMODULE_DEFN(start_kPStaticModules
);
322 NSMODULE_DEFN(end_kPStaticModules
);
324 /* The content between start_kPStaticModules and end_kPStaticModules is gathered
325 * by the linker from various objects containing symbols in a specific section.
326 * ASAN considers (rightfully) the use of this content as a global buffer
327 * overflow. But this is a deliberate and well-considered choice, with no proper
328 * way to make ASAN happy. */
331 nsComponentManagerImpl::InitializeStaticModules()
333 if (sStaticModules
) {
337 sStaticModules
= new nsTArray
<const mozilla::Module
*>;
338 for (const mozilla::Module
* const* staticModules
=
339 &NSMODULE_NAME(start_kPStaticModules
) + 1;
340 staticModules
< &NSMODULE_NAME(end_kPStaticModules
); ++staticModules
)
341 if (*staticModules
) { // ASAN adds padding
342 sStaticModules
->AppendElement(*staticModules
);
346 nsTArray
<nsComponentManagerImpl::ComponentLocation
>*
347 nsComponentManagerImpl::sModuleLocations
;
350 nsComponentManagerImpl::InitializeModuleLocations()
352 if (sModuleLocations
) {
356 sModuleLocations
= new nsTArray
<ComponentLocation
>;
360 nsComponentManagerImpl::Init()
362 PR_ASSERT(NOT_INITIALIZED
== mStatus
);
364 if (!nsComponentManagerLog
) {
365 nsComponentManagerLog
= PR_NewLogModule("nsComponentManager");
368 // Initialize our arena
369 PL_INIT_ARENA_POOL(&mArena
, "ComponentManagerArena", NS_CM_BLOCK_SIZE
);
371 nsCOMPtr
<nsIFile
> greDir
=
372 GetLocationFromDirectoryService(NS_GRE_DIR
);
373 nsCOMPtr
<nsIFile
> appDir
=
374 GetLocationFromDirectoryService(NS_XPCOM_CURRENT_PROCESS_DIR
);
376 InitializeStaticModules();
378 nsresult rv
= mNativeModuleLoader
.Init();
383 nsCategoryManager::GetSingleton()->SuppressNotifications(true);
385 RegisterModule(&kXPCOMModule
, nullptr);
387 for (uint32_t i
= 0; i
< sStaticModules
->Length(); ++i
) {
388 RegisterModule((*sStaticModules
)[i
], nullptr);
391 // The overall order in which chrome.manifests are expected to be treated
394 // - greDir's omni.ja
396 // - appDir's omni.ja
398 InitializeModuleLocations();
399 ComponentLocation
* cl
= sModuleLocations
->AppendElement();
400 nsCOMPtr
<nsIFile
> lf
= CloneAndAppend(greDir
,
401 NS_LITERAL_CSTRING("chrome.manifest"));
402 cl
->type
= NS_COMPONENT_LOCATION
;
403 cl
->location
.Init(lf
);
405 nsRefPtr
<nsZipArchive
> greOmnijar
=
406 mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE
);
408 cl
= sModuleLocations
->AppendElement();
409 cl
->type
= NS_COMPONENT_LOCATION
;
410 cl
->location
.Init(greOmnijar
, "chrome.manifest");
414 appDir
->Equals(greDir
, &equals
);
416 cl
= sModuleLocations
->AppendElement();
417 cl
->type
= NS_COMPONENT_LOCATION
;
418 lf
= CloneAndAppend(appDir
, NS_LITERAL_CSTRING("chrome.manifest"));
419 cl
->location
.Init(lf
);
422 nsRefPtr
<nsZipArchive
> appOmnijar
=
423 mozilla::Omnijar::GetReader(mozilla::Omnijar::APP
);
425 cl
= sModuleLocations
->AppendElement();
426 cl
->type
= NS_COMPONENT_LOCATION
;
427 cl
->location
.Init(appOmnijar
, "chrome.manifest");
430 RereadChromeManifests(false);
432 nsCategoryManager::GetSingleton()->SuppressNotifications(false);
434 RegisterWeakMemoryReporter(this);
436 // Unfortunately, we can't register the nsCategoryManager memory reporter
437 // in its constructor (which is triggered by the GetSingleton() call
438 // above) because the memory reporter manager isn't initialized at that
439 // point. So we wait until now.
440 nsCategoryManager::GetSingleton()->InitMemoryReporter();
442 PR_LOG(nsComponentManagerLog
, PR_LOG_DEBUG
,
443 ("nsComponentManager: Initialized."));
451 nsComponentManagerImpl::RegisterModule(const mozilla::Module
* aModule
,
454 mLock
.AssertNotCurrentThreadOwns();
457 // Scope the monitor so that we don't hold it while calling into the
459 MutexLock
lock(mLock
);
464 aFile
->GetURIString(uri
);
465 NS_ASSERTION(!mKnownModules
.Get(uri
),
466 "Must not register a binary module twice.");
468 m
= new KnownModule(aModule
, *aFile
);
469 mKnownModules
.Put(uri
, m
);
471 m
= new KnownModule(aModule
);
472 mKnownStaticModules
.AppendElement(m
);
475 if (aModule
->mCIDs
) {
476 const mozilla::Module::CIDEntry
* entry
;
477 for (entry
= aModule
->mCIDs
; entry
->cid
; ++entry
) {
478 RegisterCIDEntryLocked(entry
, m
);
482 if (aModule
->mContractIDs
) {
483 const mozilla::Module::ContractIDEntry
* entry
;
484 for (entry
= aModule
->mContractIDs
; entry
->contractid
; ++entry
) {
485 RegisterContractIDLocked(entry
);
487 MOZ_ASSERT(!entry
->cid
, "Incorrectly terminated contract list");
491 if (aModule
->mCategoryEntries
) {
492 const mozilla::Module::CategoryEntry
* entry
;
493 for (entry
= aModule
->mCategoryEntries
; entry
->category
; ++entry
)
494 nsCategoryManager::GetSingleton()->AddCategoryEntry(entry
->category
,
501 ProcessSelectorMatches(Module::ProcessSelector aSelector
)
503 if (aSelector
== Module::ANY_PROCESS
) {
507 GoannaProcessType type
= XRE_GetProcessType();
509 case Module::MAIN_PROCESS_ONLY
:
510 return type
== GoannaProcessType_Default
;
511 case Module::CONTENT_PROCESS_ONLY
:
512 return type
== GoannaProcessType_Content
;
514 MOZ_CRASH("invalid process aSelector");
519 nsComponentManagerImpl::RegisterCIDEntryLocked(
520 const mozilla::Module::CIDEntry
* aEntry
,
521 KnownModule
* aModule
)
523 mLock
.AssertCurrentThreadOwns();
525 if (!ProcessSelectorMatches(aEntry
->processSelector
)) {
529 nsFactoryEntry
* f
= mFactories
.Get(*aEntry
->cid
);
531 NS_WARNING("Re-registering a CID?");
533 char idstr
[NSID_LENGTH
];
534 aEntry
->cid
->ToProvidedString(idstr
);
538 existing
= f
->mModule
->Description();
540 existing
= "<unknown module>";
542 SafeMutexAutoUnlock
unlock(mLock
);
543 LogMessage("While registering XPCOM module %s, trying to re-register CID '%s' already registered by %s.",
544 aModule
->Description().get(),
550 f
= new nsFactoryEntry(aEntry
, aModule
);
551 mFactories
.Put(*aEntry
->cid
, f
);
555 nsComponentManagerImpl::RegisterContractIDLocked(
556 const mozilla::Module::ContractIDEntry
* aEntry
)
558 mLock
.AssertCurrentThreadOwns();
560 if (!ProcessSelectorMatches(aEntry
->processSelector
)) {
564 nsFactoryEntry
* f
= mFactories
.Get(*aEntry
->cid
);
566 NS_WARNING("No CID found when attempting to map contract ID");
568 char idstr
[NSID_LENGTH
];
569 aEntry
->cid
->ToProvidedString(idstr
);
571 SafeMutexAutoUnlock
unlock(mLock
);
572 LogMessage("Could not map contract ID '%s' to CID %s because no implementation of the CID is registered.",
579 mContractIDs
.Put(nsDependentCString(aEntry
->contractid
), f
);
583 CutExtension(nsCString
& aPath
)
585 int32_t dotPos
= aPath
.RFindChar('.');
586 if (kNotFound
== dotPos
) {
589 aPath
.Cut(0, dotPos
+ 1);
594 DoRegisterManifest(NSLocationType aType
,
599 MOZ_ASSERT(!aXPTOnly
|| !nsComponentManagerImpl::gComponentManager
);
601 FileLocation::Data data
;
602 nsAutoArrayPtr
<char> buf
;
603 nsresult rv
= aFile
.GetData(data
);
604 if (NS_SUCCEEDED(rv
)) {
605 rv
= data
.GetSize(&len
);
607 if (NS_SUCCEEDED(rv
)) {
608 buf
= new char[len
+ 1];
609 rv
= data
.Copy(buf
, len
);
611 if (NS_SUCCEEDED(rv
)) {
613 ParseManifest(aType
, aFile
, buf
, aChromeOnly
, aXPTOnly
);
618 nsComponentManagerImpl::RegisterManifest(NSLocationType aType
,
622 DoRegisterManifest(aType
, aFile
, aChromeOnly
, false);
626 nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext
& aCx
,
627 int aLineNo
, char* const* aArgv
)
629 char* file
= aArgv
[0];
630 FileLocation
f(aCx
.mFile
, file
);
631 RegisterManifest(aCx
.mType
, f
, aCx
.mChromeOnly
);
635 nsComponentManagerImpl::ManifestBinaryComponent(ManifestProcessingContext
& aCx
,
639 if (aCx
.mFile
.IsZip()) {
640 NS_WARNING("Cannot load binary components from a jar.");
641 LogMessageWithContext(aCx
.mFile
, aLineNo
,
642 "Cannot load binary components from a jar.");
646 FileLocation
f(aCx
.mFile
, aArgv
[0]);
650 if (mKnownModules
.Get(uri
)) {
651 NS_WARNING("Attempting to register a binary component twice.");
652 LogMessageWithContext(aCx
.mFile
, aLineNo
,
653 "Attempting to register a binary component twice.");
657 const mozilla::Module
* m
= mNativeModuleLoader
.LoadModule(f
);
658 // The native module loader should report an error here, we don't have to
663 RegisterModule(m
, &f
);
667 DoRegisterXPT(FileLocation
& aFile
)
669 #ifdef MOZ_B2G_LOADER
670 if (IsRegisteredXPTIInfo(aFile
)) {
676 FileLocation::Data data
;
677 nsAutoArrayPtr
<char> buf
;
678 nsresult rv
= aFile
.GetData(data
);
679 if (NS_SUCCEEDED(rv
)) {
680 rv
= data
.GetSize(&len
);
682 if (NS_SUCCEEDED(rv
)) {
684 rv
= data
.Copy(buf
, len
);
686 if (NS_SUCCEEDED(rv
)) {
687 XPTInterfaceInfoManager::GetSingleton()->RegisterBuffer(buf
, len
);
688 #ifdef MOZ_B2G_LOADER
689 MarkRegisteredXPTIInfo(aFile
);
693 aFile
.GetURIString(uri
);
694 LogMessage("Could not read '%s'.", uri
.get());
699 nsComponentManagerImpl::ManifestXPT(ManifestProcessingContext
& aCx
,
700 int aLineNo
, char* const* aArgv
)
702 FileLocation
f(aCx
.mFile
, aArgv
[0]);
707 nsComponentManagerImpl::ManifestComponent(ManifestProcessingContext
& aCx
,
708 int aLineNo
, char* const* aArgv
)
710 mLock
.AssertNotCurrentThreadOwns();
713 char* file
= aArgv
[1];
716 if (!cid
.Parse(id
)) {
717 LogMessageWithContext(aCx
.mFile
, aLineNo
,
718 "Malformed CID: '%s'.", id
);
722 // Precompute the hash/file data outside of the lock
723 FileLocation
fl(aCx
.mFile
, file
);
725 fl
.GetURIString(hash
);
727 MutexLock
lock(mLock
);
728 nsFactoryEntry
* f
= mFactories
.Get(cid
);
730 char idstr
[NSID_LENGTH
];
731 cid
.ToProvidedString(idstr
);
735 existing
= f
->mModule
->Description();
737 existing
= "<unknown module>";
742 LogMessageWithContext(aCx
.mFile
, aLineNo
,
743 "Trying to re-register CID '%s' already registered by %s.",
751 km
= mKnownModules
.Get(hash
);
753 km
= new KnownModule(fl
);
754 mKnownModules
.Put(hash
, km
);
759 PL_ARENA_ALLOCATE(place
, &mArena
, sizeof(nsCID
));
760 nsID
* permanentCID
= static_cast<nsID
*>(place
);
763 PL_ARENA_ALLOCATE(place
, &mArena
, sizeof(mozilla::Module::CIDEntry
));
764 mozilla::Module::CIDEntry
* e
= new (place
) mozilla::Module::CIDEntry();
765 e
->cid
= permanentCID
;
767 f
= new nsFactoryEntry(e
, km
);
768 mFactories
.Put(cid
, f
);
772 nsComponentManagerImpl::ManifestContract(ManifestProcessingContext
& aCx
,
773 int aLineNo
, char* const* aArgv
)
775 mLock
.AssertNotCurrentThreadOwns();
777 char* contract
= aArgv
[0];
781 if (!cid
.Parse(id
)) {
782 LogMessageWithContext(aCx
.mFile
, aLineNo
,
783 "Malformed CID: '%s'.", id
);
787 MutexLock
lock(mLock
);
788 nsFactoryEntry
* f
= mFactories
.Get(cid
);
791 LogMessageWithContext(aCx
.mFile
, aLineNo
,
792 "Could not map contract ID '%s' to CID %s because no implementation of the CID is registered.",
797 mContractIDs
.Put(nsDependentCString(contract
), f
);
801 nsComponentManagerImpl::ManifestCategory(ManifestProcessingContext
& aCx
,
802 int aLineNo
, char* const* aArgv
)
804 char* category
= aArgv
[0];
805 char* key
= aArgv
[1];
806 char* value
= aArgv
[2];
808 nsCategoryManager::GetSingleton()->
809 AddCategoryEntry(category
, key
, value
);
813 nsComponentManagerImpl::RereadChromeManifests(bool aChromeOnly
)
815 for (uint32_t i
= 0; i
< sModuleLocations
->Length(); ++i
) {
816 ComponentLocation
& l
= sModuleLocations
->ElementAt(i
);
817 RegisterManifest(l
.type
, l
.location
, aChromeOnly
);
822 nsComponentManagerImpl::KnownModule::EnsureLoader()
826 mFile
.GetURIString(extension
);
827 CutExtension(extension
);
829 nsComponentManagerImpl::gComponentManager
->LoaderForExtension(extension
);
835 nsComponentManagerImpl::KnownModule::Load()
841 if (!EnsureLoader()) {
845 mModule
= mLoader
->LoadModule(mFile
);
853 if (mModule
->loadProc
) {
854 nsresult rv
= mModule
->loadProc();
866 nsComponentManagerImpl::KnownModule::Description() const
870 mFile
.GetURIString(s
);
872 s
= "<static module>";
877 nsresult
nsComponentManagerImpl::Shutdown(void)
879 PR_ASSERT(NORMAL
== mStatus
);
881 mStatus
= SHUTDOWN_IN_PROGRESS
;
883 // Shutdown the component manager
884 PR_LOG(nsComponentManagerLog
, PR_LOG_DEBUG
,
885 ("nsComponentManager: Beginning Shutdown."));
887 UnregisterWeakMemoryReporter(this);
889 // Release all cached factories
890 mContractIDs
.Clear();
891 mFactories
.Clear(); // XXX release the objects, don't just clear
893 mKnownModules
.Clear();
894 mKnownStaticModules
.Clear();
896 delete sStaticModules
;
897 delete sModuleLocations
;
898 #ifdef MOZ_B2G_LOADER
899 delete sXPTIInfosBook
;
900 sXPTIInfosBook
= nullptr;
904 mNativeModuleLoader
.UnloadLibraries();
906 // delete arena for strings and small objects
907 PL_FinishArenaPool(&mArena
);
909 mStatus
= SHUTDOWN_COMPLETE
;
911 PR_LOG(nsComponentManagerLog
, PR_LOG_DEBUG
,
912 ("nsComponentManager: Shutdown complete."));
917 nsComponentManagerImpl::~nsComponentManagerImpl()
919 PR_LOG(nsComponentManagerLog
, PR_LOG_DEBUG
,
920 ("nsComponentManager: Beginning destruction."));
922 if (SHUTDOWN_COMPLETE
!= mStatus
) {
926 PR_LOG(nsComponentManagerLog
, PR_LOG_DEBUG
,
927 ("nsComponentManager: Destroyed."));
930 NS_IMPL_ISUPPORTS(nsComponentManagerImpl
,
933 nsIComponentRegistrar
,
934 nsISupportsWeakReference
,
935 nsIInterfaceRequestor
,
939 nsComponentManagerImpl::GetInterface(const nsIID
& aUuid
, void** aResult
)
941 NS_WARNING("This isn't supported");
942 // fall through to QI as anything QIable is a superset of what can be
943 // got via the GetInterface()
944 return QueryInterface(aUuid
, aResult
);
948 nsComponentManagerImpl::GetFactoryEntry(const char* aContractID
,
949 uint32_t aContractIDLen
)
951 SafeMutexAutoLock
lock(mLock
);
952 return mContractIDs
.Get(nsDependentCString(aContractID
, aContractIDLen
));
957 nsComponentManagerImpl::GetFactoryEntry(const nsCID
& aClass
)
959 SafeMutexAutoLock
lock(mLock
);
960 return mFactories
.Get(aClass
);
963 already_AddRefed
<nsIFactory
>
964 nsComponentManagerImpl::FindFactory(const nsCID
& aClass
)
966 nsFactoryEntry
* e
= GetFactoryEntry(aClass
);
971 return e
->GetFactory();
974 already_AddRefed
<nsIFactory
>
975 nsComponentManagerImpl::FindFactory(const char* aContractID
,
976 uint32_t aContractIDLen
)
978 nsFactoryEntry
* entry
= GetFactoryEntry(aContractID
, aContractIDLen
);
983 return entry
->GetFactory();
989 * Given a classID, this finds the singleton ClassObject that implements the CID.
990 * Returns an interface of type aIID off the singleton classobject.
993 nsComponentManagerImpl::GetClassObject(const nsCID
& aClass
, const nsIID
& aIID
,
999 if (PR_LOG_TEST(nsComponentManagerLog
, PR_LOG_DEBUG
)) {
1000 char* buf
= aClass
.ToString();
1001 PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf
);
1008 PR_ASSERT(aResult
!= nullptr);
1010 nsCOMPtr
<nsIFactory
> factory
= FindFactory(aClass
);
1012 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1015 rv
= factory
->QueryInterface(aIID
, aResult
);
1017 PR_LOG(nsComponentManagerLog
, PR_LOG_WARNING
,
1018 ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
1025 nsComponentManagerImpl::GetClassObjectByContractID(const char* aContractID
,
1029 if (NS_WARN_IF(!aResult
) ||
1030 NS_WARN_IF(!aContractID
)) {
1031 return NS_ERROR_INVALID_ARG
;
1038 if (PR_LOG_TEST(nsComponentManagerLog
, PR_LOG_DEBUG
)) {
1039 PR_LogPrint("nsComponentManager: GetClassObject(%s)", aContractID
);
1043 nsCOMPtr
<nsIFactory
> factory
= FindFactory(aContractID
, strlen(aContractID
));
1045 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1048 rv
= factory
->QueryInterface(aIID
, aResult
);
1050 PR_LOG(nsComponentManagerLog
, PR_LOG_WARNING
,
1051 ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
1059 * Create an instance of an object that implements an interface and belongs
1060 * to the implementation aClass using the factory. The factory is immediately
1061 * released and not held onto for any longer.
1064 nsComponentManagerImpl::CreateInstance(const nsCID
& aClass
,
1065 nsISupports
* aDelegate
,
1069 // test this first, since there's no point in creating a component during
1070 // shutdown -- whether it's available or not would depend on the order it
1071 // occurs in the list
1072 if (gXPCOMShuttingDown
) {
1073 // When processing shutdown, don't process new GetService() requests
1074 #ifdef SHOW_DENIED_ON_SHUTDOWN
1075 nsXPIDLCString cid
, iid
;
1076 cid
.Adopt(aClass
.ToString());
1077 iid
.Adopt(aIID
.ToString());
1078 fprintf(stderr
, "Creating new instance on shutdown. Denied.\n"
1079 " CID: %s\n IID: %s\n", cid
.get(), iid
.get());
1080 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1081 return NS_ERROR_UNEXPECTED
;
1085 return NS_ERROR_NULL_POINTER
;
1089 nsFactoryEntry
* entry
= GetFactoryEntry(aClass
);
1092 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1095 #ifdef SHOW_CI_ON_EXISTING_SERVICE
1096 if (entry
->mServiceObject
) {
1098 cid
.Adopt(aClass
.ToString());
1099 nsAutoCString message
;
1100 message
= NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
1102 NS_LITERAL_CSTRING("\" when a service for this CID already exists!");
1103 NS_ERROR(message
.get());
1108 nsCOMPtr
<nsIFactory
> factory
= entry
->GetFactory();
1110 rv
= factory
->CreateInstance(aDelegate
, aIID
, aResult
);
1111 if (NS_SUCCEEDED(rv
) && !*aResult
) {
1112 NS_ERROR("Factory did not return an object but returned success!");
1113 rv
= NS_ERROR_SERVICE_NOT_FOUND
;
1116 // Translate error values
1117 rv
= NS_ERROR_FACTORY_NOT_REGISTERED
;
1121 if (PR_LOG_TEST(nsComponentManagerLog
, PR_LOG_WARNING
)) {
1122 char* buf
= aClass
.ToString();
1123 PR_LOG(nsComponentManagerLog
, PR_LOG_WARNING
,
1124 ("nsComponentManager: CreateInstance(%s) %s", buf
,
1125 NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
1136 * CreateInstanceByContractID()
1138 * A variant of CreateInstance() that creates an instance of the object that
1139 * implements the interface aIID and whose implementation has a contractID aContractID.
1141 * This is only a convenience routine that turns around can calls the
1142 * CreateInstance() with classid and iid.
1145 nsComponentManagerImpl::CreateInstanceByContractID(const char* aContractID
,
1146 nsISupports
* aDelegate
,
1150 if (NS_WARN_IF(!aContractID
)) {
1151 return NS_ERROR_INVALID_ARG
;
1154 // test this first, since there's no point in creating a component during
1155 // shutdown -- whether it's available or not would depend on the order it
1156 // occurs in the list
1157 if (gXPCOMShuttingDown
) {
1158 // When processing shutdown, don't process new GetService() requests
1159 #ifdef SHOW_DENIED_ON_SHUTDOWN
1161 iid
.Adopt(aIID
.ToString());
1162 fprintf(stderr
, "Creating new instance on shutdown. Denied.\n"
1163 " ContractID: %s\n IID: %s\n", aContractID
, iid
.get());
1164 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1165 return NS_ERROR_UNEXPECTED
;
1169 return NS_ERROR_NULL_POINTER
;
1173 nsFactoryEntry
* entry
= GetFactoryEntry(aContractID
, strlen(aContractID
));
1176 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1179 #ifdef SHOW_CI_ON_EXISTING_SERVICE
1180 if (entry
->mServiceObject
) {
1181 nsAutoCString message
;
1183 NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
1184 nsDependentCString(aContractID
) +
1185 NS_LITERAL_CSTRING("\" when a service for this CID already exists! "
1186 "Add it to abusedContracts to track down the service consumer.");
1187 NS_ERROR(message
.get());
1192 nsCOMPtr
<nsIFactory
> factory
= entry
->GetFactory();
1195 rv
= factory
->CreateInstance(aDelegate
, aIID
, aResult
);
1196 if (NS_SUCCEEDED(rv
) && !*aResult
) {
1197 NS_ERROR("Factory did not return an object but returned success!");
1198 rv
= NS_ERROR_SERVICE_NOT_FOUND
;
1201 // Translate error values
1202 rv
= NS_ERROR_FACTORY_NOT_REGISTERED
;
1205 PR_LOG(nsComponentManagerLog
, PR_LOG_WARNING
,
1206 ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID
,
1207 NS_SUCCEEDED(rv
) ? "succeeded" : "FAILED"));
1212 static PLDHashOperator
1213 FreeFactoryEntries(const nsID
& aCID
,
1214 nsFactoryEntry
* aEntry
,
1217 aEntry
->mFactory
= nullptr;
1218 aEntry
->mServiceObject
= nullptr;
1219 return PL_DHASH_NEXT
;
1223 nsComponentManagerImpl::FreeServices()
1225 NS_ASSERTION(gXPCOMShuttingDown
,
1226 "Must be shutting down in order to free all services");
1228 if (!gXPCOMShuttingDown
) {
1229 return NS_ERROR_FAILURE
;
1232 mFactories
.EnumerateRead(FreeFactoryEntries
, nullptr);
1236 // This should only ever be called within the monitor!
1237 nsComponentManagerImpl::PendingServiceInfo
*
1238 nsComponentManagerImpl::AddPendingService(const nsCID
& aServiceCID
,
1241 PendingServiceInfo
* newInfo
= mPendingServices
.AppendElement();
1243 newInfo
->cid
= &aServiceCID
;
1244 newInfo
->thread
= aThread
;
1249 // This should only ever be called within the monitor!
1251 nsComponentManagerImpl::RemovePendingService(const nsCID
& aServiceCID
)
1253 uint32_t pendingCount
= mPendingServices
.Length();
1254 for (uint32_t index
= 0; index
< pendingCount
; ++index
) {
1255 const PendingServiceInfo
& info
= mPendingServices
.ElementAt(index
);
1256 if (info
.cid
->Equals(aServiceCID
)) {
1257 mPendingServices
.RemoveElementAt(index
);
1263 // This should only ever be called within the monitor!
1265 nsComponentManagerImpl::GetPendingServiceThread(const nsCID
& aServiceCID
) const
1267 uint32_t pendingCount
= mPendingServices
.Length();
1268 for (uint32_t index
= 0; index
< pendingCount
; ++index
) {
1269 const PendingServiceInfo
& info
= mPendingServices
.ElementAt(index
);
1270 if (info
.cid
->Equals(aServiceCID
)) {
1278 nsComponentManagerImpl::GetService(const nsCID
& aClass
,
1282 // test this first, since there's no point in returning a service during
1283 // shutdown -- whether it's available or not would depend on the order it
1284 // occurs in the list
1285 if (gXPCOMShuttingDown
) {
1286 // When processing shutdown, don't process new GetService() requests
1287 #ifdef SHOW_DENIED_ON_SHUTDOWN
1288 nsXPIDLCString cid
, iid
;
1289 cid
.Adopt(aClass
.ToString());
1290 iid
.Adopt(aIID
.ToString());
1291 fprintf(stderr
, "Getting service on shutdown. Denied.\n"
1292 " CID: %s\n IID: %s\n", cid
.get(), iid
.get());
1293 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1294 return NS_ERROR_UNEXPECTED
;
1297 // `service` must be released after the lock is released, so it must be
1298 // declared before the lock in this C++ block.
1299 nsCOMPtr
<nsISupports
> service
;
1300 MutexLock
lock(mLock
);
1302 nsFactoryEntry
* entry
= mFactories
.Get(aClass
);
1304 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1307 if (entry
->mServiceObject
) {
1309 return entry
->mServiceObject
->QueryInterface(aIID
, aResult
);
1312 PRThread
* currentPRThread
= PR_GetCurrentThread();
1313 MOZ_ASSERT(currentPRThread
, "This should never be null!");
1315 // Needed to optimize the event loop below.
1316 nsIThread
* currentThread
= nullptr;
1318 PRThread
* pendingPRThread
;
1319 while ((pendingPRThread
= GetPendingServiceThread(aClass
))) {
1320 if (pendingPRThread
== currentPRThread
) {
1321 NS_ERROR("Recursive GetService!");
1322 return NS_ERROR_NOT_AVAILABLE
;
1326 SafeMutexAutoUnlock
unlockPending(mLock
);
1328 if (!currentThread
) {
1329 currentThread
= NS_GetCurrentThread();
1330 MOZ_ASSERT(currentThread
, "This should never be null!");
1333 // This will process a single event or yield the thread if no event is
1335 if (!NS_ProcessNextEvent(currentThread
, false)) {
1336 PR_Sleep(PR_INTERVAL_NO_WAIT
);
1340 // It's still possible that the other thread failed to create the
1341 // service so we're not guaranteed to have an entry or service yet.
1342 if (entry
->mServiceObject
) {
1344 return entry
->mServiceObject
->QueryInterface(aIID
, aResult
);
1348 PendingServiceInfo
* newInfo
=
1350 AddPendingService(aClass
, currentPRThread
);
1351 NS_ASSERTION(newInfo
, "Failed to add info to the array!");
1353 // We need to not be holding the service manager's lock while calling
1354 // CreateInstance, because it invokes user code which could try to re-enter
1355 // the service manager:
1359 SafeMutexAutoUnlock
unlock(mLock
);
1360 rv
= CreateInstance(aClass
, nullptr, aIID
, getter_AddRefs(service
));
1362 if (NS_SUCCEEDED(rv
) && !service
) {
1363 NS_ERROR("Factory did not return an object but returned success");
1364 return NS_ERROR_SERVICE_NOT_FOUND
;
1368 pendingPRThread
= GetPendingServiceThread(aClass
);
1369 MOZ_ASSERT(pendingPRThread
== currentPRThread
,
1370 "Pending service array has been changed!");
1372 RemovePendingService(aClass
);
1374 if (NS_FAILED(rv
)) {
1378 NS_ASSERTION(!entry
->mServiceObject
, "Created two instances of a service!");
1380 entry
->mServiceObject
= service
.forget();
1383 nsISupports
** sresult
= reinterpret_cast<nsISupports
**>(aResult
);
1384 *sresult
= entry
->mServiceObject
;
1385 (*sresult
)->AddRef();
1391 nsComponentManagerImpl::IsServiceInstantiated(const nsCID
& aClass
,
1395 // Now we want to get the service if we already got it. If not, we don't want
1396 // to create an instance of it. mmh!
1398 // test this first, since there's no point in returning a service during
1399 // shutdown -- whether it's available or not would depend on the order it
1400 // occurs in the list
1401 if (gXPCOMShuttingDown
) {
1402 // When processing shutdown, don't process new GetService() requests
1403 #ifdef SHOW_DENIED_ON_SHUTDOWN
1404 nsXPIDLCString cid
, iid
;
1405 cid
.Adopt(aClass
.ToString());
1406 iid
.Adopt(aIID
.ToString());
1407 fprintf(stderr
, "Checking for service on shutdown. Denied.\n"
1408 " CID: %s\n IID: %s\n", cid
.get(), iid
.get());
1409 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1410 return NS_ERROR_UNEXPECTED
;
1413 nsresult rv
= NS_ERROR_SERVICE_NOT_AVAILABLE
;
1414 nsFactoryEntry
* entry
;
1417 SafeMutexAutoLock
lock(mLock
);
1418 entry
= mFactories
.Get(aClass
);
1421 if (entry
&& entry
->mServiceObject
) {
1422 nsCOMPtr
<nsISupports
> service
;
1423 rv
= entry
->mServiceObject
->QueryInterface(aIID
, getter_AddRefs(service
));
1424 *aResult
= (service
!= nullptr);
1431 nsComponentManagerImpl::IsServiceInstantiatedByContractID(
1432 const char* aContractID
,
1436 // Now we want to get the service if we already got it. If not, we don't want
1437 // to create an instance of it. mmh!
1439 // test this first, since there's no point in returning a service during
1440 // shutdown -- whether it's available or not would depend on the order it
1441 // occurs in the list
1442 if (gXPCOMShuttingDown
) {
1443 // When processing shutdown, don't process new GetService() requests
1444 #ifdef SHOW_DENIED_ON_SHUTDOWN
1446 iid
.Adopt(aIID
.ToString());
1447 fprintf(stderr
, "Checking for service on shutdown. Denied.\n"
1448 " ContractID: %s\n IID: %s\n", aContractID
, iid
.get());
1449 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1450 return NS_ERROR_UNEXPECTED
;
1453 nsresult rv
= NS_ERROR_SERVICE_NOT_AVAILABLE
;
1454 nsFactoryEntry
* entry
;
1456 SafeMutexAutoLock
lock(mLock
);
1457 entry
= mContractIDs
.Get(nsDependentCString(aContractID
));
1460 if (entry
&& entry
->mServiceObject
) {
1461 nsCOMPtr
<nsISupports
> service
;
1462 rv
= entry
->mServiceObject
->QueryInterface(aIID
, getter_AddRefs(service
));
1463 *aResult
= (service
!= nullptr);
1470 nsComponentManagerImpl::GetServiceByContractID(const char* aContractID
,
1474 // test this first, since there's no point in returning a service during
1475 // shutdown -- whether it's available or not would depend on the order it
1476 // occurs in the list
1477 if (gXPCOMShuttingDown
) {
1478 // When processing shutdown, don't process new GetService() requests
1479 #ifdef SHOW_DENIED_ON_SHUTDOWN
1481 iid
.Adopt(aIID
.ToString());
1482 fprintf(stderr
, "Getting service on shutdown. Denied.\n"
1483 " ContractID: %s\n IID: %s\n", aContractID
, iid
.get());
1484 #endif /* SHOW_DENIED_ON_SHUTDOWN */
1485 return NS_ERROR_UNEXPECTED
;
1488 // `service` must be released after the lock is released, so it must be
1489 // declared before the lock in this C++ block.
1490 nsCOMPtr
<nsISupports
> service
;
1491 MutexLock
lock(mLock
);
1493 nsFactoryEntry
* entry
= mContractIDs
.Get(nsDependentCString(aContractID
));
1495 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1498 if (entry
->mServiceObject
) {
1499 // We need to not be holding the service manager's monitor while calling
1500 // QueryInterface, because it invokes user code which could try to re-enter
1501 // the service manager, or try to grab some other lock/monitor/condvar
1502 // and deadlock, e.g. bug 282743.
1503 // `entry` is valid until XPCOM shutdown, so we can safely use it after
1504 // exiting the lock.
1506 return entry
->mServiceObject
->QueryInterface(aIID
, aResult
);
1509 PRThread
* currentPRThread
= PR_GetCurrentThread();
1510 MOZ_ASSERT(currentPRThread
, "This should never be null!");
1512 // Needed to optimize the event loop below.
1513 nsIThread
* currentThread
= nullptr;
1515 PRThread
* pendingPRThread
;
1516 while ((pendingPRThread
= GetPendingServiceThread(*entry
->mCIDEntry
->cid
))) {
1517 if (pendingPRThread
== currentPRThread
) {
1518 NS_ERROR("Recursive GetService!");
1519 return NS_ERROR_NOT_AVAILABLE
;
1522 SafeMutexAutoUnlock
unlockPending(mLock
);
1524 if (!currentThread
) {
1525 currentThread
= NS_GetCurrentThread();
1526 MOZ_ASSERT(currentThread
, "This should never be null!");
1529 // This will process a single event or yield the thread if no event is
1531 if (!NS_ProcessNextEvent(currentThread
, false)) {
1532 PR_Sleep(PR_INTERVAL_NO_WAIT
);
1536 if (currentThread
&& entry
->mServiceObject
) {
1537 // If we have a currentThread then we must have waited on another thread
1538 // to create the service. Grab it now if that succeeded.
1540 return entry
->mServiceObject
->QueryInterface(aIID
, aResult
);
1544 PendingServiceInfo
* newInfo
=
1546 AddPendingService(*entry
->mCIDEntry
->cid
, currentPRThread
);
1547 NS_ASSERTION(newInfo
, "Failed to add info to the array!");
1549 // We need to not be holding the service manager's lock while calling
1550 // CreateInstance, because it invokes user code which could try to re-enter
1551 // the service manager:
1555 SafeMutexAutoUnlock
unlock(mLock
);
1556 rv
= CreateInstanceByContractID(aContractID
, nullptr, aIID
,
1557 getter_AddRefs(service
));
1559 if (NS_SUCCEEDED(rv
) && !service
) {
1560 NS_ERROR("Factory did not return an object but returned success");
1561 return NS_ERROR_SERVICE_NOT_FOUND
;
1565 pendingPRThread
= GetPendingServiceThread(*entry
->mCIDEntry
->cid
);
1566 MOZ_ASSERT(pendingPRThread
== currentPRThread
,
1567 "Pending service array has been changed!");
1569 RemovePendingService(*entry
->mCIDEntry
->cid
);
1571 if (NS_FAILED(rv
)) {
1575 NS_ASSERTION(!entry
->mServiceObject
, "Created two instances of a service!");
1577 entry
->mServiceObject
= service
.forget();
1581 nsISupports
** sresult
= reinterpret_cast<nsISupports
**>(aResult
);
1582 *sresult
= entry
->mServiceObject
;
1583 (*sresult
)->AddRef();
1588 already_AddRefed
<mozilla::ModuleLoader
>
1589 nsComponentManagerImpl::LoaderForExtension(const nsACString
& aExt
)
1591 nsCOMPtr
<mozilla::ModuleLoader
> loader
= mLoaderMap
.Get(aExt
);
1593 loader
= do_GetServiceFromCategory("module-loader",
1594 PromiseFlatCString(aExt
).get());
1599 mLoaderMap
.Put(aExt
, loader
);
1602 return loader
.forget();
1606 nsComponentManagerImpl::RegisterFactory(const nsCID
& aClass
,
1608 const char* aContractID
,
1609 nsIFactory
* aFactory
)
1612 // If a null factory is passed in, this call just wants to reset
1613 // the contract ID to point to an existing CID entry.
1615 return NS_ERROR_INVALID_ARG
;
1618 SafeMutexAutoLock
lock(mLock
);
1619 nsFactoryEntry
* oldf
= mFactories
.Get(aClass
);
1621 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1624 mContractIDs
.Put(nsDependentCString(aContractID
), oldf
);
1628 nsAutoPtr
<nsFactoryEntry
> f(new nsFactoryEntry(aClass
, aFactory
));
1630 SafeMutexAutoLock
lock(mLock
);
1631 nsFactoryEntry
* oldf
= mFactories
.Get(aClass
);
1633 return NS_ERROR_FACTORY_EXISTS
;
1637 mContractIDs
.Put(nsDependentCString(aContractID
), f
);
1640 mFactories
.Put(aClass
, f
.forget());
1646 nsComponentManagerImpl::UnregisterFactory(const nsCID
& aClass
,
1647 nsIFactory
* aFactory
)
1649 // Don't release the dying factory or service object until releasing
1650 // the component manager monitor.
1651 nsCOMPtr
<nsIFactory
> dyingFactory
;
1652 nsCOMPtr
<nsISupports
> dyingServiceObject
;
1655 SafeMutexAutoLock
lock(mLock
);
1656 nsFactoryEntry
* f
= mFactories
.Get(aClass
);
1657 if (!f
|| f
->mFactory
!= aFactory
) {
1658 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1661 mFactories
.Remove(aClass
);
1663 // This might leave a stale contractid -> factory mapping in
1664 // place, so null out the factory entry (see
1665 // nsFactoryEntry::GetFactory)
1666 f
->mFactory
.swap(dyingFactory
);
1667 f
->mServiceObject
.swap(dyingServiceObject
);
1674 nsComponentManagerImpl::AutoRegister(nsIFile
* aLocation
)
1676 XRE_AddManifestLocation(NS_COMPONENT_LOCATION
, aLocation
);
1681 nsComponentManagerImpl::AutoUnregister(nsIFile
* aLocation
)
1683 NS_ERROR("AutoUnregister not implemented.");
1684 return NS_ERROR_NOT_IMPLEMENTED
;
1688 nsComponentManagerImpl::RegisterFactoryLocation(const nsCID
& aCID
,
1689 const char* aClassName
,
1690 const char* aContractID
,
1692 const char* aLoaderStr
,
1695 NS_ERROR("RegisterFactoryLocation not implemented.");
1696 return NS_ERROR_NOT_IMPLEMENTED
;
1700 nsComponentManagerImpl::UnregisterFactoryLocation(const nsCID
& aCID
,
1703 NS_ERROR("UnregisterFactoryLocation not implemented.");
1704 return NS_ERROR_NOT_IMPLEMENTED
;
1708 nsComponentManagerImpl::IsCIDRegistered(const nsCID
& aClass
,
1711 *aResult
= (nullptr != GetFactoryEntry(aClass
));
1716 nsComponentManagerImpl::IsContractIDRegistered(const char* aClass
,
1719 if (NS_WARN_IF(!aClass
)) {
1720 return NS_ERROR_INVALID_ARG
;
1723 nsFactoryEntry
* entry
= GetFactoryEntry(aClass
, strlen(aClass
));
1733 static PLDHashOperator
1734 EnumerateCIDHelper(const nsID
& aId
, nsFactoryEntry
* aEntry
, void* aClosure
)
1736 nsCOMArray
<nsISupports
>* array
=
1737 static_cast<nsCOMArray
<nsISupports
>*>(aClosure
);
1738 nsCOMPtr
<nsISupportsID
> wrapper
= new nsSupportsIDImpl();
1739 wrapper
->SetData(&aId
);
1740 array
->AppendObject(wrapper
);
1741 return PL_DHASH_NEXT
;
1745 nsComponentManagerImpl::EnumerateCIDs(nsISimpleEnumerator
** aEnumerator
)
1747 nsCOMArray
<nsISupports
> array
;
1748 mFactories
.EnumerateRead(EnumerateCIDHelper
, &array
);
1750 return NS_NewArrayEnumerator(aEnumerator
, array
);
1753 static PLDHashOperator
1754 EnumerateContractsHelper(const nsACString
& aContract
, nsFactoryEntry
* aEntry
,
1757 nsTArray
<nsCString
>* array
= static_cast<nsTArray
<nsCString
>*>(aClosure
);
1758 array
->AppendElement(aContract
);
1759 return PL_DHASH_NEXT
;
1763 nsComponentManagerImpl::EnumerateContractIDs(nsISimpleEnumerator
** aEnumerator
)
1765 nsTArray
<nsCString
>* array
= new nsTArray
<nsCString
>;
1766 mContractIDs
.EnumerateRead(EnumerateContractsHelper
, array
);
1768 nsCOMPtr
<nsIUTF8StringEnumerator
> e
;
1769 nsresult rv
= NS_NewAdoptingUTF8StringEnumerator(getter_AddRefs(e
), array
);
1770 if (NS_FAILED(rv
)) {
1774 return CallQueryInterface(e
, aEnumerator
);
1778 nsComponentManagerImpl::CIDToContractID(const nsCID
& aClass
,
1781 NS_ERROR("CIDTOContractID not implemented");
1782 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1786 nsComponentManagerImpl::ContractIDToCID(const char* aContractID
,
1790 SafeMutexAutoLock
lock(mLock
);
1791 nsFactoryEntry
* entry
= mContractIDs
.Get(nsDependentCString(aContractID
));
1793 *aResult
= (nsCID
*)NS_Alloc(sizeof(nsCID
));
1794 **aResult
= *entry
->mCIDEntry
->cid
;
1799 return NS_ERROR_FACTORY_NOT_REGISTERED
;
1803 SizeOfFactoriesEntryExcludingThis(nsIDHashKey::KeyType aKey
,
1804 nsFactoryEntry
* const& aData
,
1805 MallocSizeOf aMallocSizeOf
,
1808 return aData
->SizeOfIncludingThis(aMallocSizeOf
);
1812 SizeOfContractIDsEntryExcludingThis(nsCStringHashKey::KeyType aKey
,
1813 nsFactoryEntry
* const& aData
,
1814 MallocSizeOf aMallocSizeOf
,
1817 // We don't measure the nsFactoryEntry data because its owned by mFactories
1818 // (which measures them in SizeOfFactoriesEntryExcludingThis).
1819 return aKey
.SizeOfExcludingThisMustBeUnshared(aMallocSizeOf
);
1822 MOZ_DEFINE_MALLOC_SIZE_OF(ComponentManagerMallocSizeOf
)
1825 nsComponentManagerImpl::CollectReports(nsIHandleReportCallback
* aHandleReport
,
1826 nsISupports
* aData
, bool aAnonymize
)
1828 return MOZ_COLLECT_REPORT("explicit/xpcom/component-manager",
1829 KIND_HEAP
, UNITS_BYTES
,
1830 SizeOfIncludingThis(ComponentManagerMallocSizeOf
),
1831 "Memory used for the XPCOM component manager.");
1835 nsComponentManagerImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
)
1837 size_t n
= aMallocSizeOf(this);
1838 n
+= mLoaderMap
.SizeOfExcludingThis(nullptr, aMallocSizeOf
);
1839 n
+= mFactories
.SizeOfExcludingThis(SizeOfFactoriesEntryExcludingThis
,
1841 n
+= mContractIDs
.SizeOfExcludingThis(SizeOfContractIDsEntryExcludingThis
,
1844 n
+= sStaticModules
->SizeOfIncludingThis(aMallocSizeOf
);
1845 n
+= sModuleLocations
->SizeOfIncludingThis(aMallocSizeOf
);
1847 n
+= mKnownStaticModules
.SizeOfExcludingThis(aMallocSizeOf
);
1848 n
+= mKnownModules
.SizeOfExcludingThis(nullptr, aMallocSizeOf
);
1850 n
+= PL_SizeOfArenaPoolExcludingPool(&mArena
, aMallocSizeOf
);
1852 n
+= mPendingServices
.SizeOfExcludingThis(aMallocSizeOf
);
1854 // Measurement of the following members may be added later if DMD finds it is
1856 // - mLoaderMap's keys and values
1858 // - sStaticModules' entries
1859 // - sModuleLocations' entries
1860 // - mNativeModuleLoader
1861 // - mKnownStaticModules' entries?
1862 // - mKnownModules' keys and values?
1867 ////////////////////////////////////////////////////////////////////////////////
1869 ////////////////////////////////////////////////////////////////////////////////
1871 nsFactoryEntry::nsFactoryEntry(const mozilla::Module::CIDEntry
* aEntry
,
1872 nsComponentManagerImpl::KnownModule
* aModule
)
1878 nsFactoryEntry::nsFactoryEntry(const nsCID
& aCID
, nsIFactory
* aFactory
)
1879 : mCIDEntry(nullptr)
1881 , mFactory(aFactory
)
1883 mozilla::Module::CIDEntry
* e
= new mozilla::Module::CIDEntry();
1884 nsCID
* cid
= new nsCID
;
1890 nsFactoryEntry::~nsFactoryEntry()
1892 // If this was a RegisterFactory entry, we own the CIDEntry/CID
1894 delete mCIDEntry
->cid
;
1899 already_AddRefed
<nsIFactory
>
1900 nsFactoryEntry::GetFactory()
1902 nsComponentManagerImpl::gComponentManager
->mLock
.AssertNotCurrentThreadOwns();
1905 // RegisterFactory then UnregisterFactory can leave an entry in mContractIDs
1906 // pointing to an unusable nsFactoryEntry.
1911 if (!mModule
->Load()) {
1915 // Don't set mFactory directly, it needs to be locked
1916 nsCOMPtr
<nsIFactory
> factory
;
1918 if (mModule
->Module()->getFactoryProc
) {
1919 factory
= mModule
->Module()->getFactoryProc(*mModule
->Module(),
1921 } else if (mCIDEntry
->getFactoryProc
) {
1922 factory
= mCIDEntry
->getFactoryProc(*mModule
->Module(), *mCIDEntry
);
1924 NS_ASSERTION(mCIDEntry
->constructorProc
, "no getfactory or constructor");
1925 factory
= new mozilla::GenericFactory(mCIDEntry
->constructorProc
);
1931 SafeMutexAutoLock
lock(nsComponentManagerImpl::gComponentManager
->mLock
);
1932 // Threads can race to set mFactory
1934 factory
.swap(mFactory
);
1937 nsCOMPtr
<nsIFactory
> factory
= mFactory
;
1938 return factory
.forget();
1942 nsFactoryEntry::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf
)
1944 size_t n
= aMallocSizeOf(this);
1946 // Measurement of the following members may be added later if DMD finds it is
1951 // - mServiceObject;
1956 ////////////////////////////////////////////////////////////////////////////////
1957 // Static Access Functions
1958 ////////////////////////////////////////////////////////////////////////////////
1961 NS_GetComponentManager(nsIComponentManager
** aResult
)
1963 if (!nsComponentManagerImpl::gComponentManager
) {
1964 return NS_ERROR_NOT_INITIALIZED
;
1967 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1972 NS_GetServiceManager(nsIServiceManager
** aResult
)
1974 if (!nsComponentManagerImpl::gComponentManager
) {
1975 return NS_ERROR_NOT_INITIALIZED
;
1978 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1984 NS_GetComponentRegistrar(nsIComponentRegistrar
** aResult
)
1986 if (!nsComponentManagerImpl::gComponentManager
) {
1987 return NS_ERROR_NOT_INITIALIZED
;
1990 NS_ADDREF(*aResult
= nsComponentManagerImpl::gComponentManager
);
1994 EXPORT_XPCOM_API(nsresult
)
1995 XRE_AddStaticComponent(const mozilla::Module
* aComponent
)
1997 nsComponentManagerImpl::InitializeStaticModules();
1998 nsComponentManagerImpl::sStaticModules
->AppendElement(aComponent
);
2000 if (nsComponentManagerImpl::gComponentManager
&&
2001 nsComponentManagerImpl::NORMAL
==
2002 nsComponentManagerImpl::gComponentManager
->mStatus
) {
2003 nsComponentManagerImpl::gComponentManager
->RegisterModule(aComponent
,
2011 nsComponentManagerImpl::AddBootstrappedManifestLocation(nsIFile
* aLocation
)
2014 nsresult rv
= aLocation
->GetPath(path
);
2015 if (NS_FAILED(rv
)) {
2019 if (Substring(path
, path
.Length() - 4).EqualsLiteral(".xpi")) {
2020 return XRE_AddJarManifestLocation(NS_BOOTSTRAPPED_LOCATION
, aLocation
);
2023 nsCOMPtr
<nsIFile
> manifest
=
2024 CloneAndAppend(aLocation
, NS_LITERAL_CSTRING("chrome.manifest"));
2025 return XRE_AddManifestLocation(NS_BOOTSTRAPPED_LOCATION
, manifest
);
2029 nsComponentManagerImpl::RemoveBootstrappedManifestLocation(nsIFile
* aLocation
)
2031 nsCOMPtr
<nsIChromeRegistry
> cr
= mozilla::services::GetChromeRegistryService();
2033 return NS_ERROR_FAILURE
;
2036 nsCOMPtr
<nsIFile
> manifest
;
2038 nsresult rv
= aLocation
->GetPath(path
);
2039 if (NS_FAILED(rv
)) {
2043 nsComponentManagerImpl::ComponentLocation elem
;
2044 elem
.type
= NS_BOOTSTRAPPED_LOCATION
;
2046 if (Substring(path
, path
.Length() - 4).EqualsLiteral(".xpi")) {
2047 elem
.location
.Init(aLocation
, "chrome.manifest");
2049 nsCOMPtr
<nsIFile
> lf
=
2050 CloneAndAppend(aLocation
, NS_LITERAL_CSTRING("chrome.manifest"));
2051 elem
.location
.Init(lf
);
2054 // Remove reference.
2055 nsComponentManagerImpl::sModuleLocations
->RemoveElement(elem
,
2056 ComponentLocationComparator());
2058 rv
= cr
->CheckForNewChrome();
2063 nsComponentManagerImpl::GetManifestLocations(nsIArray
** aLocations
)
2065 NS_ENSURE_ARG_POINTER(aLocations
);
2066 *aLocations
= nullptr;
2068 if (!sModuleLocations
) {
2069 return NS_ERROR_NOT_INITIALIZED
;
2072 nsCOMPtr
<nsIMutableArray
> locations
= nsArray::Create();
2074 for (uint32_t i
= 0; i
< sModuleLocations
->Length(); ++i
) {
2075 ComponentLocation
& l
= sModuleLocations
->ElementAt(i
);
2076 FileLocation loc
= l
.location
;
2077 nsCString uriString
;
2078 loc
.GetURIString(uriString
);
2079 nsCOMPtr
<nsIURI
> uri
;
2080 rv
= NS_NewURI(getter_AddRefs(uri
), uriString
);
2081 if (NS_SUCCEEDED(rv
)) {
2082 locations
->AppendElement(uri
, false);
2086 locations
.forget(aLocations
);
2090 #ifdef MOZ_B2G_LOADER
2094 nsComponentManagerImpl::XPTOnlyManifestManifest(
2095 XPTOnlyManifestProcessingContext
& aCx
, int aLineNo
, char* const* aArgv
)
2097 char* file
= aArgv
[0];
2098 FileLocation
f(aCx
.mFile
, file
);
2100 DoRegisterManifest(NS_COMPONENT_LOCATION
, f
, false, true);
2105 nsComponentManagerImpl::XPTOnlyManifestXPT(
2106 XPTOnlyManifestProcessingContext
& aCx
, int aLineNo
, char* const* aArgv
)
2108 FileLocation
f(aCx
.mFile
, aArgv
[0]);
2113 * To load XPT Interface Information before the component manager is ready.
2115 * With this function, B2G loader could XPT interface info. as earier
2116 * as possible to gain benefit of shared memory model of the kernel.
2119 nsComponentManagerImpl::PreloadXPT(nsIFile
* aFile
)
2121 MOZ_ASSERT(!nsComponentManagerImpl::gComponentManager
);
2122 FileLocation
location(aFile
, "chrome.manifest");
2124 DoRegisterManifest(NS_COMPONENT_LOCATION
, location
,
2125 false, true /* aXPTOnly */);
2129 PreloadXPT(nsIFile
* aOmnijarFile
)
2131 nsComponentManagerImpl::PreloadXPT(aOmnijarFile
);
2134 #endif /* MOZ_B2G_LOADER */
2136 EXPORT_XPCOM_API(nsresult
)
2137 XRE_AddManifestLocation(NSLocationType aType
, nsIFile
* aLocation
)
2139 nsComponentManagerImpl::InitializeModuleLocations();
2140 nsComponentManagerImpl::ComponentLocation
* c
=
2141 nsComponentManagerImpl::sModuleLocations
->AppendElement();
2143 c
->location
.Init(aLocation
);
2145 if (nsComponentManagerImpl::gComponentManager
&&
2146 nsComponentManagerImpl::NORMAL
==
2147 nsComponentManagerImpl::gComponentManager
->mStatus
) {
2148 nsComponentManagerImpl::gComponentManager
->RegisterManifest(aType
,
2156 EXPORT_XPCOM_API(nsresult
)
2157 XRE_AddJarManifestLocation(NSLocationType aType
, nsIFile
* aLocation
)
2159 nsComponentManagerImpl::InitializeModuleLocations();
2160 nsComponentManagerImpl::ComponentLocation
* c
=
2161 nsComponentManagerImpl::sModuleLocations
->AppendElement();
2164 c
->location
.Init(aLocation
, "chrome.manifest");
2166 if (nsComponentManagerImpl::gComponentManager
&&
2167 nsComponentManagerImpl::NORMAL
==
2168 nsComponentManagerImpl::gComponentManager
->mStatus
) {
2169 nsComponentManagerImpl::gComponentManager
->RegisterManifest(aType
,