2015-04-09 20:25:05 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
2017-08-17 00:10:56 +03:00
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2011-08-18 17:46:39 +04:00
|
|
|
|
1999-06-22 18:02:58 +04:00
|
|
|
#include <stdlib.h>
|
2000-04-25 09:11:30 +04:00
|
|
|
#include "nscore.h"
|
|
|
|
#include "nsISupports.h"
|
2001-10-16 07:35:52 +04:00
|
|
|
#include "nspr.h"
|
2002-06-15 01:33:05 +04:00
|
|
|
#include "nsCRT.h" // for atoll
|
2011-08-18 17:46:39 +04:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
#include "nsCategoryManager.h"
|
1999-06-22 18:02:58 +04:00
|
|
|
#include "nsCOMPtr.h"
|
1999-03-09 12:44:27 +03:00
|
|
|
#include "nsComponentManager.h"
|
2002-01-30 00:22:13 +03:00
|
|
|
#include "nsDirectoryService.h"
|
|
|
|
#include "nsDirectoryServiceDefs.h"
|
2002-07-18 09:09:10 +04:00
|
|
|
#include "nsCategoryManager.h"
|
2002-03-22 02:43:21 +03:00
|
|
|
#include "nsCategoryManagerUtils.h"
|
2018-10-24 19:10:29 +03:00
|
|
|
#include "nsLayoutModule.h"
|
2013-06-23 16:03:39 +04:00
|
|
|
#include "mozilla/MemoryReporting.h"
|
2005-12-13 20:55:43 +03:00
|
|
|
#include "nsIConsoleService.h"
|
2002-01-30 00:22:13 +03:00
|
|
|
#include "nsIObserverService.h"
|
|
|
|
#include "nsISimpleEnumerator.h"
|
2005-12-13 20:55:43 +03:00
|
|
|
#include "nsIStringEnumerator.h"
|
2002-09-04 03:36:13 +04:00
|
|
|
#include "nsXPCOM.h"
|
2005-07-21 17:33:43 +04:00
|
|
|
#include "nsXPCOMPrivate.h"
|
1999-08-09 09:02:25 +04:00
|
|
|
#include "nsISupportsPrimitives.h"
|
2006-03-15 07:59:42 +03:00
|
|
|
#include "nsIClassInfo.h"
|
2002-01-30 00:22:13 +03:00
|
|
|
#include "nsLocalFile.h"
|
2003-03-05 06:22:12 +03:00
|
|
|
#include "nsReadableUtils.h"
|
|
|
|
#include "nsString.h"
|
1999-03-09 12:44:27 +03:00
|
|
|
#include "prcmon.h"
|
2008-09-05 02:44:41 +04:00
|
|
|
#include "nsThreadUtils.h"
|
|
|
|
#include "prthread.h"
|
2009-01-08 11:41:55 +03:00
|
|
|
#include "private/pprthred.h"
|
2009-04-03 20:43:08 +04:00
|
|
|
#include "nsTArray.h"
|
2009-11-05 17:08:49 +03:00
|
|
|
#include "prio.h"
|
2010-06-12 00:13:26 +04:00
|
|
|
#include "ManifestParser.h"
|
2015-04-03 16:52:00 +03:00
|
|
|
#include "nsNetUtil.h"
|
2011-07-29 13:20:47 +04:00
|
|
|
#include "mozilla/Services.h"
|
2018-10-23 03:47:38 +03:00
|
|
|
#include "mozJSComponentLoader.h"
|
2002-06-15 01:33:05 +04:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
#include "mozilla/GenericFactory.h"
|
|
|
|
#include "nsSupportsPrimitives.h"
|
2013-07-05 23:20:04 +04:00
|
|
|
#include "nsArray.h"
|
|
|
|
#include "nsIMutableArray.h"
|
2010-06-10 22:11:11 +04:00
|
|
|
#include "nsArrayEnumerator.h"
|
|
|
|
#include "nsStringEnumerator.h"
|
2011-12-08 14:03:36 +04:00
|
|
|
#include "mozilla/FileUtils.h"
|
2017-05-13 03:55:47 +03:00
|
|
|
#include "mozilla/URLPreloader.h"
|
2015-10-31 20:47:14 +03:00
|
|
|
#include "mozilla/UniquePtr.h"
|
2014-07-26 04:52:00 +04:00
|
|
|
#include "nsDataHashtable.h"
|
2002-06-15 01:33:05 +04:00
|
|
|
|
2013-07-12 04:16:41 +04:00
|
|
|
#include <new> // for placement new
|
1999-03-09 12:44:27 +03:00
|
|
|
|
2010-06-15 23:38:46 +04:00
|
|
|
#include "mozilla/Omnijar.h"
|
|
|
|
|
2015-05-19 21:15:34 +03:00
|
|
|
#include "mozilla/Logging.h"
|
2015-12-23 02:09:41 +03:00
|
|
|
#include "LogModulePrefWatcher.h"
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2018-07-22 20:54:56 +03:00
|
|
|
#ifdef MOZ_MEMORY
|
|
|
|
#include "mozmemory.h"
|
|
|
|
#endif
|
|
|
|
|
Rollup of bug 645263 and bug 646259: Switch to mozilla:: sync primitives. r=cjones,dbaron,doublec,ehsan src=bsmedberg
Bug 645263, part 0: Count sync primitive ctor/dtors. r=dbaron
Bug 645263, part 1: Migrate content/media to mozilla:: sync primitives. r=doublec
Bug 645263, part 2: Migrate modules/plugin to mozilla:: sync primitives. sr=bsmedberg
Bug 645263, part 3: Migrate nsComponentManagerImpl to mozilla:: sync primitives. sr=bsmedberg
Bug 645263, part 4: Migrate everything else to mozilla:: sync primitives. r=dbaron
Bug 645263, part 5: Remove nsAutoLock.*. sr=bsmedberg
Bug 645263, part 6: Make editor test be nicer to deadlock detector. r=ehsan
Bug 645263, part 7: Disable tracemalloc backtraces for xpcshell tests. r=dbaron
Bug 646259: Fix nsCacheService to use a CondVar for notifying. r=cjones
2011-04-01 08:29:02 +04:00
|
|
|
using namespace mozilla;
|
|
|
|
|
2015-10-19 22:50:14 +03:00
|
|
|
static LazyLogModule nsComponentManagerLog("nsComponentManager");
|
1999-06-14 06:07:03 +04:00
|
|
|
|
2017-08-02 07:27:25 +03:00
|
|
|
#if 0
|
2003-06-19 03:03:08 +04:00
|
|
|
#define SHOW_DENIED_ON_SHUTDOWN
|
|
|
|
#define SHOW_CI_ON_EXISTING_SERVICE
|
2002-01-10 09:55:18 +03:00
|
|
|
#endif
|
2002-01-10 05:10:37 +03:00
|
|
|
|
2002-06-15 01:33:05 +04:00
|
|
|
NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
|
2001-09-07 01:13:11 +04:00
|
|
|
|
|
|
|
nsresult
|
2014-08-03 00:44:06 +04:00
|
|
|
nsGetServiceFromCategory::operator()(const nsIID& aIID,
|
|
|
|
void** aInstancePtr) const
|
|
|
|
{
|
|
|
|
nsresult rv;
|
2017-08-16 06:58:55 +03:00
|
|
|
nsCString value;
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCOMPtr<nsICategoryManager> catman;
|
|
|
|
nsComponentManagerImpl* compMgr = nsComponentManagerImpl::gComponentManager;
|
|
|
|
if (!compMgr) {
|
|
|
|
rv = NS_ERROR_NOT_INITIALIZED;
|
|
|
|
goto error;
|
|
|
|
}
|
2004-11-25 01:48:45 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
rv = compMgr->nsComponentManagerImpl::GetService(kCategoryManagerCID,
|
|
|
|
NS_GET_IID(nsICategoryManager),
|
|
|
|
getter_AddRefs(catman));
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
goto error;
|
|
|
|
}
|
2004-11-25 01:48:45 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
/* find the contractID for category.entry */
|
2018-07-24 03:41:06 +03:00
|
|
|
rv = catman->GetCategoryEntry(mCategory, mEntry, value);
|
2014-08-03 00:44:06 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
goto error;
|
|
|
|
}
|
2017-08-16 06:58:55 +03:00
|
|
|
if (value.IsVoid()) {
|
2014-08-03 00:44:06 +04:00
|
|
|
rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2017-08-16 06:58:55 +03:00
|
|
|
rv = compMgr->nsComponentManagerImpl::GetServiceByContractID(value.get(),
|
2014-08-03 00:44:06 +04:00
|
|
|
aIID,
|
|
|
|
aInstancePtr);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
error:
|
|
|
|
*aInstancePtr = 0;
|
|
|
|
}
|
|
|
|
if (mErrorPtr) {
|
|
|
|
*mErrorPtr = rv;
|
|
|
|
}
|
|
|
|
return rv;
|
2001-09-07 01:13:11 +04:00
|
|
|
}
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2013-03-14 00:39:28 +04:00
|
|
|
// GetService and a few other functions need to exit their mutex mid-function
|
|
|
|
// without reentering it later in the block. This class supports that
|
|
|
|
// style of early-exit that MutexAutoUnlock doesn't.
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2013-04-12 07:21:40 +04:00
|
|
|
class MOZ_STACK_CLASS MutexLock
|
2013-03-14 00:39:28 +04:00
|
|
|
{
|
|
|
|
public:
|
2014-08-05 17:21:27 +04:00
|
|
|
explicit MutexLock(SafeMutex& aMutex)
|
2014-08-03 00:44:06 +04:00
|
|
|
: mMutex(aMutex)
|
|
|
|
, mLocked(false)
|
|
|
|
{
|
|
|
|
Lock();
|
|
|
|
}
|
2013-03-14 00:39:28 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
~MutexLock()
|
|
|
|
{
|
|
|
|
if (mLocked) {
|
|
|
|
Unlock();
|
2013-03-14 00:39:28 +04:00
|
|
|
}
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
2013-03-14 00:39:28 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
void Lock()
|
|
|
|
{
|
|
|
|
NS_ASSERTION(!mLocked, "Re-entering a mutex");
|
|
|
|
mMutex.Lock();
|
|
|
|
mLocked = true;
|
|
|
|
}
|
2013-03-14 00:39:28 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
void Unlock()
|
|
|
|
{
|
|
|
|
NS_ASSERTION(mLocked, "Exiting a mutex that isn't held!");
|
|
|
|
mMutex.Unlock();
|
|
|
|
mLocked = false;
|
|
|
|
}
|
2013-03-14 00:39:28 +04:00
|
|
|
|
|
|
|
private:
|
2014-08-03 00:44:06 +04:00
|
|
|
SafeMutex& mMutex;
|
|
|
|
bool mLocked;
|
2013-03-14 00:39:28 +04:00
|
|
|
};
|
|
|
|
|
2015-07-13 18:25:42 +03:00
|
|
|
} // namespace
|
2013-03-14 00:39:28 +04:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
// this is safe to call during InitXPCOM
|
2012-06-06 06:08:30 +04:00
|
|
|
static already_AddRefed<nsIFile>
|
2014-08-03 00:44:06 +04:00
|
|
|
GetLocationFromDirectoryService(const char* aProp)
|
2001-10-23 06:28:12 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCOMPtr<nsIProperties> directoryService;
|
|
|
|
nsDirectoryService::Create(nullptr,
|
|
|
|
NS_GET_IID(nsIProperties),
|
|
|
|
getter_AddRefs(directoryService));
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!directoryService) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCOMPtr<nsIFile> file;
|
|
|
|
nsresult rv = directoryService->Get(aProp,
|
|
|
|
NS_GET_IID(nsIFile),
|
|
|
|
getter_AddRefs(file));
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return file.forget();
|
2001-10-23 06:28:12 +04:00
|
|
|
}
|
|
|
|
|
2012-06-06 06:08:30 +04:00
|
|
|
static already_AddRefed<nsIFile>
|
2014-08-03 00:44:06 +04:00
|
|
|
CloneAndAppend(nsIFile* aBase, const nsACString& aAppend)
|
2010-06-21 21:49:38 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCOMPtr<nsIFile> f;
|
|
|
|
aBase->Clone(getter_AddRefs(f));
|
|
|
|
if (!f) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2010-06-21 21:49:38 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
f->AppendNative(aAppend);
|
|
|
|
return f.forget();
|
2010-06-21 21:49:38 +04:00
|
|
|
}
|
2001-09-07 01:13:11 +04:00
|
|
|
|
1999-03-09 12:44:27 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2010-06-10 22:11:11 +04:00
|
|
|
// nsComponentManagerImpl
|
1999-03-09 12:44:27 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2008-02-21 23:39:20 +03:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
nsresult
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::Create(nsISupports* aOuter, REFNSIID aIID,
|
|
|
|
void** aResult)
|
2008-02-21 23:39:20 +03:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
if (aOuter) {
|
|
|
|
return NS_ERROR_NO_AGGREGATION;
|
|
|
|
}
|
1999-10-22 01:34:39 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!gComponentManager) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
1999-06-14 06:07:03 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return gComponentManager->QueryInterface(aIID, aResult);
|
2002-01-30 00:22:13 +03:00
|
|
|
}
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2014-08-06 17:31:21 +04:00
|
|
|
static const int CONTRACTID_HASHTABLE_INITIAL_LENGTH = 1024;
|
2013-09-02 12:41:57 +04:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
nsComponentManagerImpl::nsComponentManagerImpl()
|
2014-08-06 17:31:21 +04:00
|
|
|
: mFactories(CONTRACTID_HASHTABLE_INITIAL_LENGTH)
|
|
|
|
, mContractIDs(CONTRACTID_HASHTABLE_INITIAL_LENGTH)
|
2014-08-03 00:44:06 +04:00
|
|
|
, mLock("nsComponentManagerImpl.mLock")
|
|
|
|
, mStatus(NOT_INITIALIZED)
|
2002-01-30 00:22:13 +03:00
|
|
|
{
|
|
|
|
}
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2018-06-26 10:10:30 +03:00
|
|
|
static nsTArray<const mozilla::Module*>* sExtraStaticModules;
|
2008-02-21 23:39:20 +03:00
|
|
|
|
2018-06-26 08:40:51 +03:00
|
|
|
/* NSMODULE_DEFN places NSModules in specific sections, as per Module.h.
|
|
|
|
* The linker will group them all together, and we use tricks below to
|
|
|
|
* find the start and end of the grouped list of NSModules.
|
|
|
|
*
|
|
|
|
* On Windows, all the symbols in the .kPStaticModules* sections are
|
|
|
|
* grouped together, by lexical order of the section names. The NSModules
|
|
|
|
* themselves are in .kPStaticModules$M. We use the section name
|
|
|
|
* .kPStaticModules$A to add an empty entry that will be the first,
|
|
|
|
* and the section name .kPStaticModules$Z for another empty entry that
|
|
|
|
* will be the last. We make both null pointers, and skip them in the
|
|
|
|
* AllStaticModules range-iterator.
|
|
|
|
*
|
|
|
|
* On ELF (Linux, BSDs, ...), as well as Mingw builds, the linker itself
|
|
|
|
* provides symbols for the beginning and end of the consolidated section,
|
|
|
|
* but it only does so for sections that can be represented as C identifiers,
|
|
|
|
* so the section is named `kPStaticModules` rather than `.kPStaticModules`.
|
|
|
|
*
|
|
|
|
* We also use a linker script with BFD ld so that the sections end up
|
|
|
|
* folded into the .data.rel.ro section, but that actually breaks the above
|
|
|
|
* described behavior, so the linker script contains an additional trick
|
|
|
|
* to still provide the __start and __stop symbols (the linker script
|
|
|
|
* doesn't work with gold or lld).
|
|
|
|
*
|
|
|
|
* On Darwin, a similar setup is available through the use of some
|
|
|
|
* synthesized symbols (section$...).
|
|
|
|
*
|
|
|
|
* On all platforms, the __stop_kPStaticModules symbol is past all NSModule
|
|
|
|
* pointers.
|
|
|
|
* On Windows, the __start_kPStaticModules symbol points to an empty pointer
|
|
|
|
* preceding the first NSModule pointer. On other platforms, it points to the
|
|
|
|
* first NSModule pointer.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Dummy class to define a range-iterator for the static modules.
|
|
|
|
class AllStaticModules {};
|
|
|
|
|
2018-09-11 06:20:06 +03:00
|
|
|
#if defined(_MSC_VER) || (defined(__clang__) && defined(__MINGW32__))
|
2018-06-26 08:40:51 +03:00
|
|
|
|
|
|
|
# pragma section(".kPStaticModules$A", read)
|
|
|
|
NSMODULE_ASAN_BLACKLIST __declspec(allocate(".kPStaticModules$A"), dllexport)
|
|
|
|
extern mozilla::Module const* const __start_kPStaticModules = nullptr;
|
|
|
|
|
|
|
|
mozilla::Module const* const* begin(AllStaticModules& _) {
|
|
|
|
return &__start_kPStaticModules + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
# pragma section(".kPStaticModules$Z", read)
|
|
|
|
NSMODULE_ASAN_BLACKLIST __declspec(allocate(".kPStaticModules$Z"), dllexport)
|
|
|
|
extern mozilla::Module const* const __stop_kPStaticModules = nullptr;
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
# if defined(__ELF__) || (defined(_WIN32) && defined(__GNUC__))
|
|
|
|
|
|
|
|
extern "C" mozilla::Module const* const __start_kPStaticModules;
|
|
|
|
extern "C" mozilla::Module const* const __stop_kPStaticModules;
|
|
|
|
|
|
|
|
# elif defined(__MACH__)
|
|
|
|
|
|
|
|
extern mozilla::Module const *const __start_kPStaticModules __asm("section$start$__DATA$.kPStaticModules");
|
|
|
|
extern mozilla::Module const* const __stop_kPStaticModules __asm("section$end$__DATA$.kPStaticModules");
|
|
|
|
|
|
|
|
# else
|
|
|
|
# error Do not know how to find NSModules.
|
|
|
|
# endif
|
|
|
|
|
|
|
|
mozilla::Module const* const* begin(AllStaticModules& _) {
|
|
|
|
return &__start_kPStaticModules;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
mozilla::Module const* const* end(AllStaticModules& _) {
|
|
|
|
return &__stop_kPStaticModules;
|
|
|
|
}
|
2013-11-19 08:45:31 +04:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
/* static */ void
|
|
|
|
nsComponentManagerImpl::InitializeStaticModules()
|
2002-01-30 00:22:13 +03:00
|
|
|
{
|
2018-06-26 10:10:30 +03:00
|
|
|
if (sExtraStaticModules) {
|
2014-08-03 00:44:06 +04:00
|
|
|
return;
|
|
|
|
}
|
1999-09-01 01:40:21 +04:00
|
|
|
|
2018-06-26 10:10:30 +03:00
|
|
|
sExtraStaticModules = new nsTArray<const mozilla::Module*>;
|
2002-01-30 00:22:13 +03:00
|
|
|
}
|
|
|
|
|
2010-06-12 00:13:26 +04:00
|
|
|
nsTArray<nsComponentManagerImpl::ComponentLocation>*
|
|
|
|
nsComponentManagerImpl::sModuleLocations;
|
2010-06-10 22:11:11 +04:00
|
|
|
|
|
|
|
/* static */ void
|
|
|
|
nsComponentManagerImpl::InitializeModuleLocations()
|
2002-01-30 00:22:13 +03:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
if (sModuleLocations) {
|
|
|
|
return;
|
|
|
|
}
|
2010-06-10 22:11:11 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
sModuleLocations = new nsTArray<ComponentLocation>;
|
2002-01-30 00:22:13 +03:00
|
|
|
}
|
2001-06-21 00:21:49 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsresult
|
|
|
|
nsComponentManagerImpl::Init()
|
2002-01-30 00:22:13 +03:00
|
|
|
{
|
2016-06-28 20:47:22 +03:00
|
|
|
MOZ_ASSERT(NOT_INITIALIZED == mStatus);
|
2004-01-22 04:01:19 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCOMPtr<nsIFile> greDir =
|
|
|
|
GetLocationFromDirectoryService(NS_GRE_DIR);
|
|
|
|
nsCOMPtr<nsIFile> appDir =
|
|
|
|
GetLocationFromDirectoryService(NS_XPCOM_CURRENT_PROCESS_DIR);
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
InitializeStaticModules();
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCategoryManager::GetSingleton()->SuppressNotifications(true);
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2018-10-23 03:47:24 +03:00
|
|
|
RegisterModule(&kXPCOMModule);
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2018-06-26 10:10:30 +03:00
|
|
|
for (auto module : AllStaticModules()) {
|
2018-06-28 09:53:25 +03:00
|
|
|
if (module) { // On local Windows builds, the list may contain null
|
|
|
|
// pointers from padding.
|
2018-10-23 03:47:24 +03:00
|
|
|
RegisterModule(module);
|
2018-06-28 09:53:25 +03:00
|
|
|
}
|
2018-06-26 10:10:30 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < sExtraStaticModules->Length(); ++i) {
|
2018-10-23 03:47:24 +03:00
|
|
|
RegisterModule((*sExtraStaticModules)[i]);
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2018-10-24 19:10:29 +03:00
|
|
|
// This needs to be called very early, before anything in nsLayoutModule is
|
|
|
|
// used, and before any calls are made into the JS engine.
|
|
|
|
nsLayoutModuleInitialize();
|
|
|
|
|
2016-08-23 08:57:36 +03:00
|
|
|
bool loadChromeManifests = (XRE_GetProcessType() != GeckoProcessType_GPU);
|
|
|
|
if (loadChromeManifests) {
|
|
|
|
// The overall order in which chrome.manifests are expected to be treated
|
|
|
|
// is the following:
|
|
|
|
// - greDir
|
|
|
|
// - greDir's omni.ja
|
|
|
|
// - appDir
|
|
|
|
// - appDir's omni.ja
|
|
|
|
|
|
|
|
InitializeModuleLocations();
|
|
|
|
ComponentLocation* cl = sModuleLocations->AppendElement();
|
|
|
|
nsCOMPtr<nsIFile> lf = CloneAndAppend(greDir,
|
|
|
|
NS_LITERAL_CSTRING("chrome.manifest"));
|
2015-05-01 17:23:44 +03:00
|
|
|
cl->type = NS_APP_LOCATION;
|
2014-09-25 09:47:03 +04:00
|
|
|
cl->location.Init(lf);
|
|
|
|
|
2016-08-23 08:57:36 +03:00
|
|
|
RefPtr<nsZipArchive> greOmnijar =
|
|
|
|
mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
|
|
|
|
if (greOmnijar) {
|
|
|
|
cl = sModuleLocations->AppendElement();
|
|
|
|
cl->type = NS_APP_LOCATION;
|
|
|
|
cl->location.Init(greOmnijar, "chrome.manifest");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool equals = false;
|
|
|
|
appDir->Equals(greDir, &equals);
|
|
|
|
if (!equals) {
|
|
|
|
cl = sModuleLocations->AppendElement();
|
|
|
|
cl->type = NS_APP_LOCATION;
|
|
|
|
lf = CloneAndAppend(appDir, NS_LITERAL_CSTRING("chrome.manifest"));
|
|
|
|
cl->location.Init(lf);
|
|
|
|
}
|
2014-09-25 09:47:03 +04:00
|
|
|
|
2016-08-23 08:57:36 +03:00
|
|
|
RefPtr<nsZipArchive> appOmnijar =
|
|
|
|
mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
|
|
|
|
if (appOmnijar) {
|
|
|
|
cl = sModuleLocations->AppendElement();
|
|
|
|
cl->type = NS_APP_LOCATION;
|
|
|
|
cl->location.Init(appOmnijar, "chrome.manifest");
|
|
|
|
}
|
|
|
|
|
|
|
|
RereadChromeManifests(false);
|
|
|
|
}
|
2010-09-09 07:37:11 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCategoryManager::GetSingleton()->SuppressNotifications(false);
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
RegisterWeakMemoryReporter(this);
|
2015-12-23 02:09:41 +03:00
|
|
|
|
|
|
|
// NB: The logging preference watcher needs to be registered late enough in
|
|
|
|
// startup that it's okay to use the preference system, but also as soon as
|
|
|
|
// possible so that log modules enabled via preferences are turned on as
|
|
|
|
// early as possible.
|
|
|
|
//
|
|
|
|
// We can't initialize the preference watcher when the log module manager is
|
|
|
|
// initialized, as a number of things attempt to start logging before the
|
|
|
|
// preference system is initialized.
|
|
|
|
//
|
|
|
|
// The preference system is registered as a component so at this point during
|
|
|
|
// component manager initialization we know it is setup and we can register
|
|
|
|
// for notifications.
|
|
|
|
LogModulePrefWatcher::RegisterPrefWatcher();
|
2012-10-19 16:07:36 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// Unfortunately, we can't register the nsCategoryManager memory reporter
|
|
|
|
// in its constructor (which is triggered by the GetSingleton() call
|
|
|
|
// above) because the memory reporter manager isn't initialized at that
|
|
|
|
// point. So we wait until now.
|
|
|
|
nsCategoryManager::GetSingleton()->InitMemoryReporter();
|
2012-10-19 16:07:36 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
|
2014-09-25 09:47:03 +04:00
|
|
|
("nsComponentManager: Initialized."));
|
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
mStatus = NORMAL;
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_OK;
|
2002-01-30 00:22:13 +03:00
|
|
|
}
|
|
|
|
|
2016-08-23 08:57:36 +03:00
|
|
|
static bool
|
|
|
|
ProcessSelectorMatches(Module::ProcessSelector aSelector)
|
|
|
|
{
|
|
|
|
GeckoProcessType type = XRE_GetProcessType();
|
|
|
|
if (type == GeckoProcessType_GPU) {
|
|
|
|
return !!(aSelector & Module::ALLOW_IN_GPU_PROCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aSelector & Module::MAIN_PROCESS_ONLY) {
|
|
|
|
return type == GeckoProcessType_Default;
|
|
|
|
}
|
|
|
|
if (aSelector & Module::CONTENT_PROCESS_ONLY) {
|
|
|
|
return type == GeckoProcessType_Content;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const int kModuleVersionWithSelector = 51;
|
|
|
|
|
2018-07-22 20:54:56 +03:00
|
|
|
template<typename T>
|
|
|
|
static void
|
|
|
|
AssertNotMallocAllocated(T* aPtr)
|
|
|
|
{
|
|
|
|
#if defined(DEBUG) && defined(MOZ_MEMORY)
|
|
|
|
jemalloc_ptr_info_t info;
|
|
|
|
jemalloc_ptr_info((void*)aPtr, &info);
|
|
|
|
MOZ_ASSERT(info.tag == TagUnknown);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
static void
|
|
|
|
AssertNotStackAllocated(T* aPtr)
|
|
|
|
{
|
2018-08-16 21:35:50 +03:00
|
|
|
// On all of our supported platforms, the stack grows down. Any address
|
|
|
|
// located below the address of our argument is therefore guaranteed not to be
|
|
|
|
// stack-allocated by the caller.
|
|
|
|
//
|
|
|
|
// For addresses above our argument, things get trickier. The main thread
|
|
|
|
// stack is traditionally placed at the top of the program's address space,
|
|
|
|
// but that is becoming less reliable as more and more systems adopt address
|
|
|
|
// space layout randomization strategies, so we have to guess how much space
|
|
|
|
// above our argument pointer we need to care about.
|
|
|
|
//
|
|
|
|
// On most systems, we're guaranteed at least several KiB at the top of each
|
|
|
|
// stack for TLS. We'd probably be safe assuming at least 4KiB in the stack
|
|
|
|
// segment above our argument address, but safer is... well, safer.
|
|
|
|
//
|
|
|
|
// For threads with huge stacks, it's theoretically possible that we could
|
|
|
|
// wind up being passed a stack-allocated string from farther up the stack,
|
|
|
|
// but this is a best-effort thing, so we'll assume we only care about the
|
|
|
|
// immediate caller. For that case, max 2KiB per stack frame is probably a
|
|
|
|
// reasonable guess most of the time, and is less than the ~4KiB that we
|
|
|
|
// expect for TLS, so go with that to avoid the risk of bumping into heap
|
|
|
|
// data just above the stack.
|
|
|
|
#ifdef DEBUG
|
|
|
|
static constexpr size_t kFuzz = 2048;
|
|
|
|
|
|
|
|
MOZ_ASSERT(uintptr_t(aPtr) < uintptr_t(&aPtr) ||
|
|
|
|
uintptr_t(aPtr) > uintptr_t(&aPtr) + kFuzz);
|
2018-08-22 21:31:45 +03:00
|
|
|
#endif
|
2018-07-22 20:54:56 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline nsCString
|
|
|
|
AsLiteralCString(const char* aStr)
|
|
|
|
{
|
|
|
|
AssertNotMallocAllocated(aStr);
|
|
|
|
AssertNotStackAllocated(aStr);
|
|
|
|
|
|
|
|
nsCString str;
|
|
|
|
str.AssignLiteral(aStr, strlen(aStr));
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
void
|
2018-10-23 03:47:24 +03:00
|
|
|
nsComponentManagerImpl::RegisterModule(const mozilla::Module* aModule)
|
2002-01-30 00:22:13 +03:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
mLock.AssertNotCurrentThreadOwns();
|
|
|
|
|
2016-08-23 08:57:36 +03:00
|
|
|
if (aModule->mVersion >= kModuleVersionWithSelector &&
|
|
|
|
!ProcessSelectorMatches(aModule->selector))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
{
|
|
|
|
// Scope the monitor so that we don't hold it while calling into the
|
|
|
|
// category manager.
|
|
|
|
MutexLock lock(mLock);
|
|
|
|
|
2018-10-23 03:47:24 +03:00
|
|
|
KnownModule* m = new KnownModule(aModule);
|
|
|
|
mKnownStaticModules.AppendElement(m);
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (aModule->mCIDs) {
|
|
|
|
const mozilla::Module::CIDEntry* entry;
|
|
|
|
for (entry = aModule->mCIDs; entry->cid; ++entry) {
|
|
|
|
RegisterCIDEntryLocked(entry, m);
|
|
|
|
}
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
2014-08-03 00:44:06 +04:00
|
|
|
|
|
|
|
if (aModule->mContractIDs) {
|
|
|
|
const mozilla::Module::ContractIDEntry* entry;
|
|
|
|
for (entry = aModule->mContractIDs; entry->contractid; ++entry) {
|
|
|
|
RegisterContractIDLocked(entry);
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(!entry->cid, "Incorrectly terminated contract list");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aModule->mCategoryEntries) {
|
|
|
|
const mozilla::Module::CategoryEntry* entry;
|
|
|
|
for (entry = aModule->mCategoryEntries; entry->category; ++entry)
|
2018-07-24 03:41:06 +03:00
|
|
|
nsCategoryManager::GetSingleton()->AddCategoryEntry(
|
|
|
|
AsLiteralCString(entry->category),
|
|
|
|
AsLiteralCString(entry->entry),
|
|
|
|
AsLiteralCString(entry->value));
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
2010-06-11 20:03:06 +04:00
|
|
|
}
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
void
|
2013-03-14 00:39:28 +04:00
|
|
|
nsComponentManagerImpl::RegisterCIDEntryLocked(
|
|
|
|
const mozilla::Module::CIDEntry* aEntry,
|
|
|
|
KnownModule* aModule)
|
2002-01-30 00:22:13 +03:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
mLock.AssertCurrentThreadOwns();
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!ProcessSelectorMatches(aEntry->processSelector)) {
|
|
|
|
return;
|
|
|
|
}
|
2014-02-10 04:11:37 +04:00
|
|
|
|
2018-07-22 05:09:25 +03:00
|
|
|
if (auto entry = mFactories.LookupForAdd(aEntry->cid)) {
|
2017-06-28 02:03:17 +03:00
|
|
|
nsFactoryEntry* f = entry.Data();
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_WARNING("Re-registering a CID?");
|
|
|
|
|
|
|
|
char idstr[NSID_LENGTH];
|
|
|
|
aEntry->cid->ToProvidedString(idstr);
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCString existing;
|
|
|
|
if (f->mModule) {
|
|
|
|
existing = f->mModule->Description();
|
|
|
|
} else {
|
|
|
|
existing = "<unknown module>";
|
|
|
|
}
|
|
|
|
SafeMutexAutoUnlock unlock(mLock);
|
|
|
|
LogMessage("While registering XPCOM module %s, trying to re-register CID '%s' already registered by %s.",
|
|
|
|
aModule->Description().get(),
|
|
|
|
idstr,
|
|
|
|
existing.get());
|
2017-06-28 02:03:17 +03:00
|
|
|
} else {
|
|
|
|
entry.OrInsert([aEntry, aModule] () { return new nsFactoryEntry(aEntry, aModule); });
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
2002-01-30 00:22:13 +03:00
|
|
|
}
|
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
void
|
2013-03-14 00:39:28 +04:00
|
|
|
nsComponentManagerImpl::RegisterContractIDLocked(
|
|
|
|
const mozilla::Module::ContractIDEntry* aEntry)
|
2003-01-29 01:07:53 +03:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
mLock.AssertCurrentThreadOwns();
|
2003-06-19 03:03:08 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!ProcessSelectorMatches(aEntry->processSelector)) {
|
|
|
|
return;
|
|
|
|
}
|
2014-02-10 04:11:37 +04:00
|
|
|
|
2018-07-22 05:09:25 +03:00
|
|
|
nsFactoryEntry* f = mFactories.Get(aEntry->cid);
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!f) {
|
2014-10-09 03:08:28 +04:00
|
|
|
NS_WARNING("No CID found when attempting to map contract ID");
|
2010-06-28 21:55:57 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
char idstr[NSID_LENGTH];
|
|
|
|
aEntry->cid->ToProvidedString(idstr);
|
2010-06-28 21:55:57 +04:00
|
|
|
|
2014-10-09 03:08:28 +04:00
|
|
|
SafeMutexAutoUnlock unlock(mLock);
|
2014-08-03 00:44:06 +04:00
|
|
|
LogMessage("Could not map contract ID '%s' to CID %s because no implementation of the CID is registered.",
|
|
|
|
aEntry->contractid,
|
|
|
|
idstr);
|
2003-06-19 03:03:08 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-07-22 20:54:56 +03:00
|
|
|
mContractIDs.Put(AsLiteralCString(aEntry->contractid), f);
|
2003-01-29 01:07:53 +03:00
|
|
|
}
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2010-07-02 17:53:19 +04:00
|
|
|
static void
|
2014-08-03 00:44:06 +04:00
|
|
|
CutExtension(nsCString& aPath)
|
2010-07-02 17:53:19 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
int32_t dotPos = aPath.RFindChar('.');
|
|
|
|
if (kNotFound == dotPos) {
|
|
|
|
aPath.Truncate();
|
|
|
|
} else {
|
|
|
|
aPath.Cut(0, dotPos + 1);
|
|
|
|
}
|
2010-07-02 17:53:19 +04:00
|
|
|
}
|
|
|
|
|
2014-07-26 04:52:00 +04:00
|
|
|
static void
|
|
|
|
DoRegisterManifest(NSLocationType aType,
|
2014-08-03 00:44:06 +04:00
|
|
|
FileLocation& aFile,
|
2018-03-09 00:58:29 +03:00
|
|
|
bool aChromeOnly)
|
2010-09-09 07:37:11 +04:00
|
|
|
{
|
2017-05-13 03:55:47 +03:00
|
|
|
auto result = URLPreloader::Read(aFile);
|
|
|
|
if (result.isOk()) {
|
|
|
|
nsCString buf(result.unwrap());
|
|
|
|
|
2018-03-09 00:58:29 +03:00
|
|
|
ParseManifest(aType, aFile, buf.BeginWriting(), aChromeOnly);
|
2014-08-03 00:44:06 +04:00
|
|
|
} else if (NS_BOOTSTRAPPED_LOCATION != aType) {
|
|
|
|
nsCString uri;
|
|
|
|
aFile.GetURIString(uri);
|
|
|
|
LogMessage("Could not read chrome manifest '%s'.", uri.get());
|
|
|
|
}
|
2010-08-04 22:09:21 +04:00
|
|
|
}
|
|
|
|
|
2014-07-26 04:52:00 +04:00
|
|
|
void
|
|
|
|
nsComponentManagerImpl::RegisterManifest(NSLocationType aType,
|
2014-08-03 00:44:06 +04:00
|
|
|
FileLocation& aFile,
|
2014-07-26 04:52:00 +04:00
|
|
|
bool aChromeOnly)
|
|
|
|
{
|
2018-03-09 00:58:29 +03:00
|
|
|
DoRegisterManifest(aType, aFile, aChromeOnly);
|
2014-07-26 04:52:00 +04:00
|
|
|
}
|
|
|
|
|
2010-07-22 18:31:29 +04:00
|
|
|
void
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext& aCx,
|
|
|
|
int aLineNo, char* const* aArgv)
|
2010-07-22 18:31:29 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
char* file = aArgv[0];
|
|
|
|
FileLocation f(aCx.mFile, file);
|
|
|
|
RegisterManifest(aCx.mType, f, aCx.mChromeOnly);
|
2010-07-22 18:31:29 +04:00
|
|
|
}
|
|
|
|
|
2010-06-12 00:13:26 +04:00
|
|
|
void
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::ManifestComponent(ManifestProcessingContext& aCx,
|
|
|
|
int aLineNo, char* const* aArgv)
|
2010-06-12 00:13:26 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
mLock.AssertNotCurrentThreadOwns();
|
2013-03-14 00:39:28 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
char* id = aArgv[0];
|
|
|
|
char* file = aArgv[1];
|
2010-06-12 00:13:26 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsID cid;
|
|
|
|
if (!cid.Parse(id)) {
|
|
|
|
LogMessageWithContext(aCx.mFile, aLineNo,
|
|
|
|
"Malformed CID: '%s'.", id);
|
|
|
|
return;
|
|
|
|
}
|
2010-06-12 00:13:26 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// Precompute the hash/file data outside of the lock
|
|
|
|
FileLocation fl(aCx.mFile, file);
|
|
|
|
nsCString hash;
|
|
|
|
fl.GetURIString(hash);
|
2013-03-14 00:39:28 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
MutexLock lock(mLock);
|
2018-07-22 05:09:25 +03:00
|
|
|
nsFactoryEntry* f = mFactories.Get(&cid);
|
|
|
|
if (f) {
|
2014-08-03 00:44:06 +04:00
|
|
|
char idstr[NSID_LENGTH];
|
|
|
|
cid.ToProvidedString(idstr);
|
|
|
|
|
|
|
|
nsCString existing;
|
|
|
|
if (f->mModule) {
|
|
|
|
existing = f->mModule->Description();
|
|
|
|
} else {
|
|
|
|
existing = "<unknown module>";
|
2010-06-12 00:13:26 +04:00
|
|
|
}
|
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
lock.Unlock();
|
2010-06-12 00:13:26 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
LogMessageWithContext(aCx.mFile, aLineNo,
|
|
|
|
"Trying to re-register CID '%s' already registered by %s.",
|
|
|
|
idstr,
|
|
|
|
existing.get());
|
|
|
|
return;
|
|
|
|
}
|
2010-06-12 00:13:26 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
KnownModule* km;
|
2010-06-12 00:13:26 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
km = mKnownModules.Get(hash);
|
|
|
|
if (!km) {
|
|
|
|
km = new KnownModule(fl);
|
|
|
|
mKnownModules.Put(hash, km);
|
|
|
|
}
|
2010-06-12 00:13:26 +04:00
|
|
|
|
2017-03-31 02:46:58 +03:00
|
|
|
void* place = mArena.Allocate(sizeof(nsCID));
|
2014-08-03 00:44:06 +04:00
|
|
|
nsID* permanentCID = static_cast<nsID*>(place);
|
|
|
|
*permanentCID = cid;
|
|
|
|
|
2017-03-31 02:46:58 +03:00
|
|
|
place = mArena.Allocate(sizeof(mozilla::Module::CIDEntry));
|
|
|
|
auto* e = new (KnownNotNull, place) mozilla::Module::CIDEntry();
|
2014-08-03 00:44:06 +04:00
|
|
|
e->cid = permanentCID;
|
|
|
|
|
2018-07-22 05:09:25 +03:00
|
|
|
mFactories.Put(permanentCID, new nsFactoryEntry(e, km));
|
2010-06-12 00:13:26 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::ManifestContract(ManifestProcessingContext& aCx,
|
|
|
|
int aLineNo, char* const* aArgv)
|
2010-06-12 00:13:26 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
mLock.AssertNotCurrentThreadOwns();
|
2013-03-14 00:39:28 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
char* contract = aArgv[0];
|
|
|
|
char* id = aArgv[1];
|
2010-06-12 00:13:26 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsID cid;
|
|
|
|
if (!cid.Parse(id)) {
|
|
|
|
LogMessageWithContext(aCx.mFile, aLineNo,
|
|
|
|
"Malformed CID: '%s'.", id);
|
|
|
|
return;
|
|
|
|
}
|
2010-06-12 00:13:26 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
MutexLock lock(mLock);
|
2018-07-22 05:09:25 +03:00
|
|
|
nsFactoryEntry* f = mFactories.Get(&cid);
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!f) {
|
|
|
|
lock.Unlock();
|
|
|
|
LogMessageWithContext(aCx.mFile, aLineNo,
|
|
|
|
"Could not map contract ID '%s' to CID %s because no implementation of the CID is registered.",
|
|
|
|
contract, id);
|
|
|
|
return;
|
|
|
|
}
|
2010-06-12 00:13:26 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
mContractIDs.Put(nsDependentCString(contract), f);
|
2010-06-12 00:13:26 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::ManifestCategory(ManifestProcessingContext& aCx,
|
|
|
|
int aLineNo, char* const* aArgv)
|
2010-06-12 00:13:26 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
char* category = aArgv[0];
|
|
|
|
char* key = aArgv[1];
|
|
|
|
char* value = aArgv[2];
|
2010-06-12 00:13:26 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCategoryManager::GetSingleton()->
|
2018-07-24 03:41:06 +03:00
|
|
|
AddCategoryEntry(nsDependentCString(category), nsDependentCString(key),
|
|
|
|
nsDependentCString(value));
|
2010-06-12 00:13:26 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2011-12-08 14:03:36 +04:00
|
|
|
nsComponentManagerImpl::RereadChromeManifests(bool aChromeOnly)
|
2010-06-12 00:13:26 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
for (uint32_t i = 0; i < sModuleLocations->Length(); ++i) {
|
|
|
|
ComponentLocation& l = sModuleLocations->ElementAt(i);
|
|
|
|
RegisterManifest(l.type, l.location, aChromeOnly);
|
|
|
|
}
|
2017-08-04 06:32:25 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
|
|
if (obs) {
|
|
|
|
obs->NotifyObservers(nullptr, "chrome-manifests-loaded", nullptr);
|
|
|
|
}
|
2010-06-12 00:13:26 +04:00
|
|
|
}
|
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
bool
|
|
|
|
nsComponentManagerImpl::KnownModule::Load()
|
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
if (mFailed) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!mModule) {
|
2018-10-23 03:47:38 +03:00
|
|
|
nsCString extension;
|
|
|
|
mFile.GetURIString(extension);
|
|
|
|
CutExtension(extension);
|
|
|
|
if (!extension.Equals("js")) {
|
2014-08-03 00:44:06 +04:00
|
|
|
return false;
|
|
|
|
}
|
2010-07-02 17:53:19 +04:00
|
|
|
|
2018-10-23 03:47:38 +03:00
|
|
|
RefPtr<mozJSComponentLoader> loader = mozJSComponentLoader::GetOrCreate();
|
|
|
|
mModule = loader->LoadModule(mFile);
|
2010-07-02 17:53:19 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!mModule) {
|
|
|
|
mFailed = true;
|
|
|
|
return false;
|
2003-03-05 06:22:12 +03:00
|
|
|
}
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
|
|
|
if (!mLoaded) {
|
|
|
|
if (mModule->loadProc) {
|
|
|
|
nsresult rv = mModule->loadProc();
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
mFailed = true;
|
|
|
|
return false;
|
|
|
|
}
|
2003-03-12 00:36:59 +03:00
|
|
|
}
|
2014-08-03 00:44:06 +04:00
|
|
|
mLoaded = true;
|
|
|
|
}
|
|
|
|
return true;
|
2005-12-03 18:27:17 +03:00
|
|
|
}
|
|
|
|
|
2010-06-28 21:55:57 +04:00
|
|
|
nsCString
|
|
|
|
nsComponentManagerImpl::KnownModule::Description() const
|
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCString s;
|
|
|
|
if (mFile) {
|
|
|
|
mFile.GetURIString(s);
|
|
|
|
} else {
|
|
|
|
s = "<static module>";
|
|
|
|
}
|
|
|
|
return s;
|
2010-06-28 21:55:57 +04:00
|
|
|
}
|
|
|
|
|
2003-06-19 03:03:08 +04:00
|
|
|
nsresult nsComponentManagerImpl::Shutdown(void)
|
2002-01-30 00:22:13 +03:00
|
|
|
{
|
2016-06-28 20:47:22 +03:00
|
|
|
MOZ_ASSERT(NORMAL == mStatus);
|
1999-10-22 01:34:39 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
mStatus = SHUTDOWN_IN_PROGRESS;
|
1999-10-22 01:34:39 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// Shutdown the component manager
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
|
2014-08-03 00:44:06 +04:00
|
|
|
("nsComponentManager: Beginning Shutdown."));
|
1999-07-31 09:55:04 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
UnregisterWeakMemoryReporter(this);
|
2012-10-19 16:07:36 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// Release all cached factories
|
|
|
|
mContractIDs.Clear();
|
|
|
|
mFactories.Clear(); // XXX release the objects, don't just clear
|
|
|
|
mKnownModules.Clear();
|
|
|
|
mKnownStaticModules.Clear();
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2018-06-26 10:10:30 +03:00
|
|
|
delete sExtraStaticModules;
|
2014-08-03 00:44:06 +04:00
|
|
|
delete sModuleLocations;
|
2010-06-26 01:27:10 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
mStatus = SHUTDOWN_COMPLETE;
|
1999-07-31 09:55:04 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
|
2014-08-03 00:44:06 +04:00
|
|
|
("nsComponentManager: Shutdown complete."));
|
1999-10-22 01:34:39 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_OK;
|
1999-10-22 01:34:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsComponentManagerImpl::~nsComponentManagerImpl()
|
|
|
|
{
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
|
2014-08-03 00:44:06 +04:00
|
|
|
("nsComponentManager: Beginning destruction."));
|
1999-10-22 01:34:39 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (SHUTDOWN_COMPLETE != mStatus) {
|
|
|
|
Shutdown();
|
|
|
|
}
|
1999-10-22 01:34:39 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
|
2014-08-03 00:44:06 +04:00
|
|
|
("nsComponentManager: Destroyed."));
|
1999-06-14 06:07:03 +04:00
|
|
|
}
|
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_IMPL_ISUPPORTS(nsComponentManagerImpl,
|
|
|
|
nsIComponentManager,
|
|
|
|
nsIServiceManager,
|
|
|
|
nsIComponentRegistrar,
|
|
|
|
nsISupportsWeakReference,
|
|
|
|
nsIInterfaceRequestor,
|
|
|
|
nsIMemoryReporter)
|
2008-02-21 23:39:20 +03:00
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
nsresult
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::GetInterface(const nsIID& aUuid, void** aResult)
|
2002-01-30 00:22:13 +03:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_WARNING("This isn't supported");
|
|
|
|
// fall through to QI as anything QIable is a superset of what can be
|
|
|
|
// got via the GetInterface()
|
|
|
|
return QueryInterface(aUuid, aResult);
|
2002-01-30 00:22:13 +03:00
|
|
|
}
|
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsFactoryEntry*
|
|
|
|
nsComponentManagerImpl::GetFactoryEntry(const char* aContractID,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aContractIDLen)
|
2010-06-10 22:11:11 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
SafeMutexAutoLock lock(mLock);
|
|
|
|
return mContractIDs.Get(nsDependentCString(aContractID, aContractIDLen));
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
1999-06-14 06:07:03 +04:00
|
|
|
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsFactoryEntry*
|
|
|
|
nsComponentManagerImpl::GetFactoryEntry(const nsCID& aClass)
|
2002-06-15 01:33:05 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
SafeMutexAutoLock lock(mLock);
|
2018-07-22 05:09:25 +03:00
|
|
|
return mFactories.Get(&aClass);
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
already_AddRefed<nsIFactory>
|
|
|
|
nsComponentManagerImpl::FindFactory(const nsCID& aClass)
|
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
nsFactoryEntry* e = GetFactoryEntry(aClass);
|
|
|
|
if (!e) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2010-06-10 22:11:11 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return e->GetFactory();
|
2002-06-15 01:33:05 +04:00
|
|
|
}
|
1999-03-09 12:44:27 +03:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
already_AddRefed<nsIFactory>
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::FindFactory(const char* aContractID,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aContractIDLen)
|
2002-06-15 01:33:05 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
nsFactoryEntry* entry = GetFactoryEntry(aContractID, aContractIDLen);
|
|
|
|
if (!entry) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2010-05-20 03:22:19 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return entry->GetFactory();
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
/**
|
|
|
|
* GetClassObject()
|
|
|
|
*
|
|
|
|
* Given a classID, this finds the singleton ClassObject that implements the CID.
|
|
|
|
* Returns an interface of type aIID off the singleton classobject.
|
|
|
|
*/
|
|
|
|
NS_IMETHODIMP
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::GetClassObject(const nsCID& aClass, const nsIID& aIID,
|
|
|
|
void** aResult)
|
2010-06-10 22:11:11 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
nsresult rv;
|
2001-11-30 10:50:03 +03:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
if (MOZ_LOG_TEST(nsComponentManagerLog, LogLevel::Debug)) {
|
2014-08-03 00:44:06 +04:00
|
|
|
char* buf = aClass.ToString();
|
|
|
|
PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf);
|
|
|
|
if (buf) {
|
2015-04-01 08:29:55 +03:00
|
|
|
free(buf);
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
2001-12-14 04:27:16 +03:00
|
|
|
|
2016-06-28 20:47:22 +03:00
|
|
|
MOZ_ASSERT(aResult != nullptr);
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCOMPtr<nsIFactory> factory = FindFactory(aClass);
|
|
|
|
if (!factory) {
|
|
|
|
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
|
}
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
rv = factory->QueryInterface(aIID, aResult);
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(nsComponentManagerLog, LogLevel::Warning,
|
2014-08-03 00:44:06 +04:00
|
|
|
("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return rv;
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
2003-06-19 03:03:08 +04:00
|
|
|
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
NS_IMETHODIMP
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::GetClassObjectByContractID(const char* aContractID,
|
|
|
|
const nsIID& aIID,
|
|
|
|
void** aResult)
|
2010-06-10 22:11:11 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
if (NS_WARN_IF(!aResult) ||
|
|
|
|
NS_WARN_IF(!aContractID)) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsresult rv;
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(nsComponentManagerLog, LogLevel::Debug,
|
2017-07-04 00:37:06 +03:00
|
|
|
("nsComponentManager: GetClassObjectByContractID(%s)", aContractID));
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCOMPtr<nsIFactory> factory = FindFactory(aContractID, strlen(aContractID));
|
|
|
|
if (!factory) {
|
|
|
|
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
|
}
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
rv = factory->QueryInterface(aIID, aResult);
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(nsComponentManagerLog, LogLevel::Warning,
|
2017-07-04 00:37:06 +03:00
|
|
|
("\t\tGetClassObjectByContractID() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return rv;
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
/**
|
|
|
|
* CreateInstance()
|
|
|
|
*
|
|
|
|
* Create an instance of an object that implements an interface and belongs
|
|
|
|
* to the implementation aClass using the factory. The factory is immediately
|
|
|
|
* released and not held onto for any longer.
|
|
|
|
*/
|
|
|
|
NS_IMETHODIMP
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::CreateInstance(const nsCID& aClass,
|
|
|
|
nsISupports* aDelegate,
|
|
|
|
const nsIID& aIID,
|
|
|
|
void** aResult)
|
|
|
|
{
|
|
|
|
// test this first, since there's no point in creating a component during
|
|
|
|
// shutdown -- whether it's available or not would depend on the order it
|
|
|
|
// occurs in the list
|
|
|
|
if (gXPCOMShuttingDown) {
|
|
|
|
// When processing shutdown, don't process new GetService() requests
|
2010-06-10 22:11:11 +04:00
|
|
|
#ifdef SHOW_DENIED_ON_SHUTDOWN
|
2017-08-02 07:27:25 +03:00
|
|
|
char cid[NSID_LENGTH], iid[NSID_LENGTH];
|
|
|
|
aClass.ToProvidedString(cid);
|
|
|
|
aIID.ToProvidedString(iid);
|
2014-08-03 00:44:06 +04:00
|
|
|
fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
|
2017-08-02 07:27:25 +03:00
|
|
|
" CID: %s\n IID: %s\n", cid, iid);
|
2010-06-10 22:11:11 +04:00
|
|
|
#endif /* SHOW_DENIED_ON_SHUTDOWN */
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
2002-06-15 01:33:05 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!aResult) {
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
*aResult = nullptr;
|
2003-06-19 03:03:08 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsFactoryEntry* entry = GetFactoryEntry(aClass);
|
2003-03-05 06:22:12 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!entry) {
|
|
|
|
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
|
}
|
2005-12-03 18:27:17 +03:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
#ifdef SHOW_CI_ON_EXISTING_SERVICE
|
2014-08-03 00:44:06 +04:00
|
|
|
if (entry->mServiceObject) {
|
2017-08-02 07:27:25 +03:00
|
|
|
char cid[NSID_LENGTH];
|
|
|
|
aClass.ToProvidedString(cid);
|
2014-08-03 00:44:06 +04:00
|
|
|
nsAutoCString message;
|
|
|
|
message = NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
|
2017-08-02 07:27:25 +03:00
|
|
|
nsDependentCString(cid) +
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_LITERAL_CSTRING("\" when a service for this CID already exists!");
|
|
|
|
NS_ERROR(message.get());
|
|
|
|
}
|
2010-06-10 22:11:11 +04:00
|
|
|
#endif
|
1999-03-09 12:44:27 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIFactory> factory = entry->GetFactory();
|
|
|
|
if (factory) {
|
|
|
|
rv = factory->CreateInstance(aDelegate, aIID, aResult);
|
|
|
|
if (NS_SUCCEEDED(rv) && !*aResult) {
|
|
|
|
NS_ERROR("Factory did not return an object but returned success!");
|
|
|
|
rv = NS_ERROR_SERVICE_NOT_FOUND;
|
2002-06-15 01:33:05 +04:00
|
|
|
}
|
2014-08-03 00:44:06 +04:00
|
|
|
} else {
|
|
|
|
// Translate error values
|
|
|
|
rv = NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
|
}
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
if (MOZ_LOG_TEST(nsComponentManagerLog, LogLevel::Warning)) {
|
2014-08-03 00:44:06 +04:00
|
|
|
char* buf = aClass.ToString();
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(nsComponentManagerLog, LogLevel::Warning,
|
2014-08-03 00:44:06 +04:00
|
|
|
("nsComponentManager: CreateInstance(%s) %s", buf,
|
|
|
|
NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
|
|
|
|
if (buf) {
|
2015-04-01 08:29:55 +03:00
|
|
|
free(buf);
|
1999-03-10 12:53:25 +03:00
|
|
|
}
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
1999-03-31 11:04:12 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return rv;
|
1999-03-09 12:44:27 +03:00
|
|
|
}
|
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
/**
|
|
|
|
* CreateInstanceByContractID()
|
|
|
|
*
|
|
|
|
* A variant of CreateInstance() that creates an instance of the object that
|
|
|
|
* implements the interface aIID and whose implementation has a contractID aContractID.
|
|
|
|
*
|
|
|
|
* This is only a convenience routine that turns around can calls the
|
|
|
|
* CreateInstance() with classid and iid.
|
|
|
|
*/
|
|
|
|
NS_IMETHODIMP
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::CreateInstanceByContractID(const char* aContractID,
|
|
|
|
nsISupports* aDelegate,
|
|
|
|
const nsIID& aIID,
|
|
|
|
void** aResult)
|
|
|
|
{
|
|
|
|
if (NS_WARN_IF(!aContractID)) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
// test this first, since there's no point in creating a component during
|
|
|
|
// shutdown -- whether it's available or not would depend on the order it
|
|
|
|
// occurs in the list
|
|
|
|
if (gXPCOMShuttingDown) {
|
|
|
|
// When processing shutdown, don't process new GetService() requests
|
2010-06-10 22:11:11 +04:00
|
|
|
#ifdef SHOW_DENIED_ON_SHUTDOWN
|
2017-08-02 07:27:25 +03:00
|
|
|
char iid[NSID_LENGTH];
|
|
|
|
aIID.ToProvidedString(iid);
|
2014-08-03 00:44:06 +04:00
|
|
|
fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
|
2017-08-02 07:27:25 +03:00
|
|
|
" ContractID: %s\n IID: %s\n", aContractID, iid);
|
2010-06-10 22:11:11 +04:00
|
|
|
#endif /* SHOW_DENIED_ON_SHUTDOWN */
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
2003-03-14 08:07:24 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!aResult) {
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
*aResult = nullptr;
|
1999-07-02 07:35:09 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsFactoryEntry* entry = GetFactoryEntry(aContractID, strlen(aContractID));
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!entry) {
|
|
|
|
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
|
}
|
1999-07-02 07:35:09 +04:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
#ifdef SHOW_CI_ON_EXISTING_SERVICE
|
2014-08-03 00:44:06 +04:00
|
|
|
if (entry->mServiceObject) {
|
|
|
|
nsAutoCString message;
|
|
|
|
message =
|
|
|
|
NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
|
|
|
|
nsDependentCString(aContractID) +
|
|
|
|
NS_LITERAL_CSTRING("\" when a service for this CID already exists! "
|
|
|
|
"Add it to abusedContracts to track down the service consumer.");
|
|
|
|
NS_ERROR(message.get());
|
|
|
|
}
|
2010-06-10 22:11:11 +04:00
|
|
|
#endif
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIFactory> factory = entry->GetFactory();
|
|
|
|
if (factory) {
|
1999-09-08 03:18:47 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
rv = factory->CreateInstance(aDelegate, aIID, aResult);
|
|
|
|
if (NS_SUCCEEDED(rv) && !*aResult) {
|
|
|
|
NS_ERROR("Factory did not return an object but returned success!");
|
|
|
|
rv = NS_ERROR_SERVICE_NOT_FOUND;
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
2014-08-03 00:44:06 +04:00
|
|
|
} else {
|
|
|
|
// Translate error values
|
|
|
|
rv = NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
|
}
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(nsComponentManagerLog, LogLevel::Warning,
|
2014-08-03 00:44:06 +04:00
|
|
|
("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID,
|
|
|
|
NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
|
2002-10-08 10:12:00 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return rv;
|
2002-06-15 01:33:05 +04:00
|
|
|
}
|
2001-11-16 05:38:23 +03:00
|
|
|
|
2002-06-15 01:33:05 +04:00
|
|
|
nsresult
|
2010-06-10 22:11:11 +04:00
|
|
|
nsComponentManagerImpl::FreeServices()
|
2002-06-15 01:33:05 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_ASSERTION(gXPCOMShuttingDown,
|
|
|
|
"Must be shutting down in order to free all services");
|
2002-06-15 01:33:05 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!gXPCOMShuttingDown) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2003-06-19 03:03:08 +04:00
|
|
|
|
2015-07-10 02:54:59 +03:00
|
|
|
for (auto iter = mFactories.Iter(); !iter.Done(); iter.Next()) {
|
2015-07-20 15:21:28 +03:00
|
|
|
nsFactoryEntry* entry = iter.UserData();
|
2015-07-10 02:54:59 +03:00
|
|
|
entry->mFactory = nullptr;
|
|
|
|
entry->mServiceObject = nullptr;
|
|
|
|
}
|
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_OK;
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
2002-06-15 01:33:05 +04:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
// This should only ever be called within the monitor!
|
|
|
|
nsComponentManagerImpl::PendingServiceInfo*
|
|
|
|
nsComponentManagerImpl::AddPendingService(const nsCID& aServiceCID,
|
|
|
|
PRThread* aThread)
|
|
|
|
{
|
|
|
|
PendingServiceInfo* newInfo = mPendingServices.AppendElement();
|
|
|
|
if (newInfo) {
|
|
|
|
newInfo->cid = &aServiceCID;
|
|
|
|
newInfo->thread = aThread;
|
|
|
|
}
|
|
|
|
return newInfo;
|
|
|
|
}
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
// This should only ever be called within the monitor!
|
|
|
|
void
|
|
|
|
nsComponentManagerImpl::RemovePendingService(const nsCID& aServiceCID)
|
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t pendingCount = mPendingServices.Length();
|
|
|
|
for (uint32_t index = 0; index < pendingCount; ++index) {
|
2010-06-10 22:11:11 +04:00
|
|
|
const PendingServiceInfo& info = mPendingServices.ElementAt(index);
|
|
|
|
if (info.cid->Equals(aServiceCID)) {
|
|
|
|
mPendingServices.RemoveElementAt(index);
|
|
|
|
return;
|
2003-06-18 15:26:27 +04:00
|
|
|
}
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
2005-12-13 20:55:43 +03:00
|
|
|
}
|
2005-12-03 18:27:17 +03:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
// This should only ever be called within the monitor!
|
|
|
|
PRThread*
|
|
|
|
nsComponentManagerImpl::GetPendingServiceThread(const nsCID& aServiceCID) const
|
2005-12-13 20:55:43 +03:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t pendingCount = mPendingServices.Length();
|
|
|
|
for (uint32_t index = 0; index < pendingCount; ++index) {
|
2010-06-10 22:11:11 +04:00
|
|
|
const PendingServiceInfo& info = mPendingServices.ElementAt(index);
|
|
|
|
if (info.cid->Equals(aServiceCID)) {
|
|
|
|
return info.thread;
|
2000-05-15 23:28:12 +04:00
|
|
|
}
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2005-12-13 20:55:43 +03:00
|
|
|
}
|
2005-12-02 19:34:42 +03:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::GetService(const nsCID& aClass,
|
|
|
|
const nsIID& aIID,
|
2014-08-03 00:44:06 +04:00
|
|
|
void** aResult)
|
2009-11-05 17:08:49 +03:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
// test this first, since there's no point in returning a service during
|
|
|
|
// shutdown -- whether it's available or not would depend on the order it
|
|
|
|
// occurs in the list
|
|
|
|
if (gXPCOMShuttingDown) {
|
|
|
|
// When processing shutdown, don't process new GetService() requests
|
2010-06-10 22:11:11 +04:00
|
|
|
#ifdef SHOW_DENIED_ON_SHUTDOWN
|
2017-08-02 07:27:25 +03:00
|
|
|
char cid[NSID_LENGTH], iid[NSID_LENGTH];
|
|
|
|
aClass.ToProvidedString(cid);
|
|
|
|
aIID.ToProvidedString(iid);
|
2014-08-03 00:44:06 +04:00
|
|
|
fprintf(stderr, "Getting service on shutdown. Denied.\n"
|
2017-08-02 07:27:25 +03:00
|
|
|
" CID: %s\n IID: %s\n", cid, iid);
|
2010-06-10 22:11:11 +04:00
|
|
|
#endif /* SHOW_DENIED_ON_SHUTDOWN */
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
2009-11-05 17:08:49 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// `service` must be released after the lock is released, so it must be
|
|
|
|
// declared before the lock in this C++ block.
|
|
|
|
nsCOMPtr<nsISupports> service;
|
|
|
|
MutexLock lock(mLock);
|
2009-11-05 17:08:49 +03:00
|
|
|
|
2018-07-22 05:09:25 +03:00
|
|
|
nsFactoryEntry* entry = mFactories.Get(&aClass);
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!entry) {
|
|
|
|
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
|
}
|
2010-05-20 03:22:19 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (entry->mServiceObject) {
|
|
|
|
lock.Unlock();
|
|
|
|
return entry->mServiceObject->QueryInterface(aIID, aResult);
|
|
|
|
}
|
2005-12-02 19:34:42 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
PRThread* currentPRThread = PR_GetCurrentThread();
|
|
|
|
MOZ_ASSERT(currentPRThread, "This should never be null!");
|
2009-10-16 10:32:29 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// Needed to optimize the event loop below.
|
|
|
|
nsIThread* currentThread = nullptr;
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
PRThread* pendingPRThread;
|
|
|
|
while ((pendingPRThread = GetPendingServiceThread(aClass))) {
|
|
|
|
if (pendingPRThread == currentPRThread) {
|
|
|
|
NS_ERROR("Recursive GetService!");
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
2013-03-14 00:39:28 +04:00
|
|
|
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
SafeMutexAutoUnlock unlockPending(mLock);
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!currentThread) {
|
|
|
|
currentThread = NS_GetCurrentThread();
|
|
|
|
MOZ_ASSERT(currentThread, "This should never be null!");
|
2000-05-15 23:28:12 +04:00
|
|
|
}
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// This will process a single event or yield the thread if no event is
|
|
|
|
// pending.
|
|
|
|
if (!NS_ProcessNextEvent(currentThread, false)) {
|
|
|
|
PR_Sleep(PR_INTERVAL_NO_WAIT);
|
2005-12-13 20:55:43 +03:00
|
|
|
}
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// It's still possible that the other thread failed to create the
|
|
|
|
// service so we're not guaranteed to have an entry or service yet.
|
|
|
|
if (entry->mServiceObject) {
|
|
|
|
lock.Unlock();
|
|
|
|
return entry->mServiceObject->QueryInterface(aIID, aResult);
|
|
|
|
}
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
#ifdef DEBUG
|
2014-08-03 00:44:06 +04:00
|
|
|
PendingServiceInfo* newInfo =
|
2010-06-10 22:11:11 +04:00
|
|
|
#endif
|
|
|
|
AddPendingService(aClass, currentPRThread);
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_ASSERTION(newInfo, "Failed to add info to the array!");
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// We need to not be holding the service manager's lock while calling
|
|
|
|
// CreateInstance, because it invokes user code which could try to re-enter
|
|
|
|
// the service manager:
|
2010-05-20 03:22:19 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsresult rv;
|
|
|
|
{
|
|
|
|
SafeMutexAutoUnlock unlock(mLock);
|
|
|
|
rv = CreateInstance(aClass, nullptr, aIID, getter_AddRefs(service));
|
|
|
|
}
|
|
|
|
if (NS_SUCCEEDED(rv) && !service) {
|
|
|
|
NS_ERROR("Factory did not return an object but returned success");
|
|
|
|
return NS_ERROR_SERVICE_NOT_FOUND;
|
|
|
|
}
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
#ifdef DEBUG
|
2014-08-03 00:44:06 +04:00
|
|
|
pendingPRThread = GetPendingServiceThread(aClass);
|
|
|
|
MOZ_ASSERT(pendingPRThread == currentPRThread,
|
|
|
|
"Pending service array has been changed!");
|
2010-06-10 22:11:11 +04:00
|
|
|
#endif
|
2014-08-03 00:44:06 +04:00
|
|
|
RemovePendingService(aClass);
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_ASSERTION(!entry->mServiceObject, "Created two instances of a service!");
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
entry->mServiceObject = service.forget();
|
2013-03-14 00:39:28 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
lock.Unlock();
|
|
|
|
nsISupports** sresult = reinterpret_cast<nsISupports**>(aResult);
|
|
|
|
*sresult = entry->mServiceObject;
|
|
|
|
(*sresult)->AddRef();
|
2013-03-14 00:39:28 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_OK;
|
2000-04-18 09:25:05 +04:00
|
|
|
}
|
|
|
|
|
2006-04-10 21:09:48 +04:00
|
|
|
NS_IMETHODIMP
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::IsServiceInstantiated(const nsCID& aClass,
|
2010-06-10 22:11:11 +04:00
|
|
|
const nsIID& aIID,
|
2014-08-03 00:44:06 +04:00
|
|
|
bool* aResult)
|
1999-08-09 09:02:25 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
// Now we want to get the service if we already got it. If not, we don't want
|
|
|
|
// to create an instance of it. mmh!
|
2010-06-10 22:11:11 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// test this first, since there's no point in returning a service during
|
|
|
|
// shutdown -- whether it's available or not would depend on the order it
|
|
|
|
// occurs in the list
|
|
|
|
if (gXPCOMShuttingDown) {
|
|
|
|
// When processing shutdown, don't process new GetService() requests
|
2010-06-10 22:11:11 +04:00
|
|
|
#ifdef SHOW_DENIED_ON_SHUTDOWN
|
2017-08-02 07:27:25 +03:00
|
|
|
char cid[NSID_LENGTH], iid[NSID_LENGTH];
|
|
|
|
aClass.ToProvidedString(cid);
|
|
|
|
aIID.ToProvidedString(iid);
|
2014-08-03 00:44:06 +04:00
|
|
|
fprintf(stderr, "Checking for service on shutdown. Denied.\n"
|
2017-08-02 07:27:25 +03:00
|
|
|
" CID: %s\n IID: %s\n", cid, iid);
|
2010-06-10 22:11:11 +04:00
|
|
|
#endif /* SHOW_DENIED_ON_SHUTDOWN */
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
1999-08-09 09:02:25 +04:00
|
|
|
|
2017-08-13 02:15:19 +03:00
|
|
|
nsresult rv = NS_OK;
|
2014-08-03 00:44:06 +04:00
|
|
|
nsFactoryEntry* entry;
|
2010-05-20 03:22:19 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
{
|
|
|
|
SafeMutexAutoLock lock(mLock);
|
2018-07-22 05:09:25 +03:00
|
|
|
entry = mFactories.Get(&aClass);
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (entry && entry->mServiceObject) {
|
|
|
|
nsCOMPtr<nsISupports> service;
|
|
|
|
rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
|
|
|
|
*aResult = (service != nullptr);
|
2017-08-13 02:15:19 +03:00
|
|
|
} else {
|
|
|
|
*aResult = false;
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return rv;
|
2001-10-23 06:28:12 +04:00
|
|
|
}
|
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::IsServiceInstantiatedByContractID(
|
|
|
|
const char* aContractID,
|
|
|
|
const nsIID& aIID,
|
|
|
|
bool* aResult)
|
|
|
|
{
|
|
|
|
// Now we want to get the service if we already got it. If not, we don't want
|
|
|
|
// to create an instance of it. mmh!
|
|
|
|
|
|
|
|
// test this first, since there's no point in returning a service during
|
|
|
|
// shutdown -- whether it's available or not would depend on the order it
|
|
|
|
// occurs in the list
|
|
|
|
if (gXPCOMShuttingDown) {
|
|
|
|
// When processing shutdown, don't process new GetService() requests
|
2010-06-10 22:11:11 +04:00
|
|
|
#ifdef SHOW_DENIED_ON_SHUTDOWN
|
2017-08-02 07:27:25 +03:00
|
|
|
char iid[NSID_LENGTH];
|
|
|
|
aIID.ToProvidedString(iid);
|
2014-08-03 00:44:06 +04:00
|
|
|
fprintf(stderr, "Checking for service on shutdown. Denied.\n"
|
2017-08-02 07:27:25 +03:00
|
|
|
" ContractID: %s\n IID: %s\n", aContractID, iid);
|
2010-06-10 22:11:11 +04:00
|
|
|
#endif /* SHOW_DENIED_ON_SHUTDOWN */
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2017-08-13 02:15:19 +03:00
|
|
|
nsresult rv = NS_OK;
|
2014-08-03 00:44:06 +04:00
|
|
|
nsFactoryEntry* entry;
|
|
|
|
{
|
|
|
|
SafeMutexAutoLock lock(mLock);
|
|
|
|
entry = mContractIDs.Get(nsDependentCString(aContractID));
|
|
|
|
}
|
2001-10-23 06:28:12 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (entry && entry->mServiceObject) {
|
|
|
|
nsCOMPtr<nsISupports> service;
|
|
|
|
rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
|
|
|
|
*aResult = (service != nullptr);
|
2017-08-13 02:15:19 +03:00
|
|
|
} else {
|
|
|
|
*aResult = false;
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
|
|
|
return rv;
|
2005-12-13 20:55:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-06-19 03:03:08 +04:00
|
|
|
NS_IMETHODIMP
|
2010-06-10 22:11:11 +04:00
|
|
|
nsComponentManagerImpl::GetServiceByContractID(const char* aContractID,
|
|
|
|
const nsIID& aIID,
|
2014-08-03 00:44:06 +04:00
|
|
|
void** aResult)
|
2001-10-23 06:28:12 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
// test this first, since there's no point in returning a service during
|
|
|
|
// shutdown -- whether it's available or not would depend on the order it
|
|
|
|
// occurs in the list
|
|
|
|
if (gXPCOMShuttingDown) {
|
|
|
|
// When processing shutdown, don't process new GetService() requests
|
2010-06-10 22:11:11 +04:00
|
|
|
#ifdef SHOW_DENIED_ON_SHUTDOWN
|
2017-08-02 07:27:25 +03:00
|
|
|
char iid[NSID_LENGTH];
|
|
|
|
aIID.ToProvidedString(iid);
|
2014-08-03 00:44:06 +04:00
|
|
|
fprintf(stderr, "Getting service on shutdown. Denied.\n"
|
2017-08-02 07:27:25 +03:00
|
|
|
" ContractID: %s\n IID: %s\n", aContractID, iid);
|
2010-06-10 22:11:11 +04:00
|
|
|
#endif /* SHOW_DENIED_ON_SHUTDOWN */
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
2005-12-02 19:34:42 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// `service` must be released after the lock is released, so it must be
|
|
|
|
// declared before the lock in this C++ block.
|
|
|
|
nsCOMPtr<nsISupports> service;
|
|
|
|
MutexLock lock(mLock);
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsFactoryEntry* entry = mContractIDs.Get(nsDependentCString(aContractID));
|
|
|
|
if (!entry) {
|
|
|
|
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
|
}
|
2008-02-21 19:23:06 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (entry->mServiceObject) {
|
|
|
|
// We need to not be holding the service manager's monitor while calling
|
|
|
|
// QueryInterface, because it invokes user code which could try to re-enter
|
|
|
|
// the service manager, or try to grab some other lock/monitor/condvar
|
|
|
|
// and deadlock, e.g. bug 282743.
|
|
|
|
// `entry` is valid until XPCOM shutdown, so we can safely use it after
|
|
|
|
// exiting the lock.
|
|
|
|
lock.Unlock();
|
|
|
|
return entry->mServiceObject->QueryInterface(aIID, aResult);
|
|
|
|
}
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
PRThread* currentPRThread = PR_GetCurrentThread();
|
|
|
|
MOZ_ASSERT(currentPRThread, "This should never be null!");
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// Needed to optimize the event loop below.
|
|
|
|
nsIThread* currentThread = nullptr;
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
PRThread* pendingPRThread;
|
|
|
|
while ((pendingPRThread = GetPendingServiceThread(*entry->mCIDEntry->cid))) {
|
|
|
|
if (pendingPRThread == currentPRThread) {
|
|
|
|
NS_ERROR("Recursive GetService!");
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
2010-06-10 22:11:11 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
SafeMutexAutoUnlock unlockPending(mLock);
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!currentThread) {
|
|
|
|
currentThread = NS_GetCurrentThread();
|
|
|
|
MOZ_ASSERT(currentThread, "This should never be null!");
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// This will process a single event or yield the thread if no event is
|
|
|
|
// pending.
|
|
|
|
if (!NS_ProcessNextEvent(currentThread, false)) {
|
|
|
|
PR_Sleep(PR_INTERVAL_NO_WAIT);
|
2005-12-13 20:55:43 +03:00
|
|
|
}
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (currentThread && entry->mServiceObject) {
|
|
|
|
// If we have a currentThread then we must have waited on another thread
|
|
|
|
// to create the service. Grab it now if that succeeded.
|
|
|
|
lock.Unlock();
|
|
|
|
return entry->mServiceObject->QueryInterface(aIID, aResult);
|
|
|
|
}
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
#ifdef DEBUG
|
2014-08-03 00:44:06 +04:00
|
|
|
PendingServiceInfo* newInfo =
|
2010-06-10 22:11:11 +04:00
|
|
|
#endif
|
|
|
|
AddPendingService(*entry->mCIDEntry->cid, currentPRThread);
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_ASSERTION(newInfo, "Failed to add info to the array!");
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// We need to not be holding the service manager's lock while calling
|
|
|
|
// CreateInstance, because it invokes user code which could try to re-enter
|
|
|
|
// the service manager:
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsresult rv;
|
|
|
|
{
|
|
|
|
SafeMutexAutoUnlock unlock(mLock);
|
|
|
|
rv = CreateInstanceByContractID(aContractID, nullptr, aIID,
|
|
|
|
getter_AddRefs(service));
|
|
|
|
}
|
|
|
|
if (NS_SUCCEEDED(rv) && !service) {
|
|
|
|
NS_ERROR("Factory did not return an object but returned success");
|
|
|
|
return NS_ERROR_SERVICE_NOT_FOUND;
|
|
|
|
}
|
2010-06-10 22:11:11 +04:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2014-08-03 00:44:06 +04:00
|
|
|
pendingPRThread = GetPendingServiceThread(*entry->mCIDEntry->cid);
|
|
|
|
MOZ_ASSERT(pendingPRThread == currentPRThread,
|
|
|
|
"Pending service array has been changed!");
|
2010-06-10 22:11:11 +04:00
|
|
|
#endif
|
2014-08-03 00:44:06 +04:00
|
|
|
RemovePendingService(*entry->mCIDEntry->cid);
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_ASSERTION(!entry->mServiceObject, "Created two instances of a service!");
|
2005-12-13 20:55:43 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
entry->mServiceObject = service.forget();
|
2013-03-14 00:39:28 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
lock.Unlock();
|
2013-03-14 00:39:28 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsISupports** sresult = reinterpret_cast<nsISupports**>(aResult);
|
|
|
|
*sresult = entry->mServiceObject;
|
|
|
|
(*sresult)->AddRef();
|
2013-03-14 00:39:28 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_OK;
|
2001-10-23 06:28:12 +04:00
|
|
|
}
|
|
|
|
|
2003-06-19 03:03:08 +04:00
|
|
|
NS_IMETHODIMP
|
2010-06-10 22:11:11 +04:00
|
|
|
nsComponentManagerImpl::RegisterFactory(const nsCID& aClass,
|
|
|
|
const char* aName,
|
|
|
|
const char* aContractID,
|
|
|
|
nsIFactory* aFactory)
|
1999-08-09 09:02:25 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!aFactory) {
|
|
|
|
// If a null factory is passed in, this call just wants to reset
|
|
|
|
// the contract ID to point to an existing CID entry.
|
|
|
|
if (!aContractID) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
2010-06-23 23:18:13 +04:00
|
|
|
}
|
|
|
|
|
2013-03-14 00:39:53 +04:00
|
|
|
SafeMutexAutoLock lock(mLock);
|
2018-07-22 05:09:25 +03:00
|
|
|
nsFactoryEntry* oldf = mFactories.Get(&aClass);
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!oldf) {
|
|
|
|
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
|
}
|
1999-08-09 09:02:25 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
mContractIDs.Put(nsDependentCString(aContractID), oldf);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2010-06-23 23:18:13 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsAutoPtr<nsFactoryEntry> f(new nsFactoryEntry(aClass, aFactory));
|
2010-06-24 00:18:08 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
SafeMutexAutoLock lock(mLock);
|
2018-07-22 05:09:25 +03:00
|
|
|
if (auto entry = mFactories.LookupForAdd(f->mCIDEntry->cid)) {
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_ERROR_FACTORY_EXISTS;
|
2017-06-28 02:03:17 +03:00
|
|
|
} else {
|
|
|
|
if (aContractID) {
|
|
|
|
mContractIDs.Put(nsDependentCString(aContractID), f);
|
|
|
|
}
|
|
|
|
entry.OrInsert([&f] () { return f.forget(); });
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
1999-08-09 09:02:25 +04:00
|
|
|
}
|
|
|
|
|
2003-06-19 03:03:08 +04:00
|
|
|
NS_IMETHODIMP
|
2010-06-10 22:11:11 +04:00
|
|
|
nsComponentManagerImpl::UnregisterFactory(const nsCID& aClass,
|
|
|
|
nsIFactory* aFactory)
|
1999-08-09 09:02:25 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
// Don't release the dying factory or service object until releasing
|
|
|
|
// the component manager monitor.
|
|
|
|
nsCOMPtr<nsIFactory> dyingFactory;
|
|
|
|
nsCOMPtr<nsISupports> dyingServiceObject;
|
2010-06-10 22:11:11 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
{
|
|
|
|
SafeMutexAutoLock lock(mLock);
|
2018-07-22 05:09:25 +03:00
|
|
|
auto entry = mFactories.Lookup(&aClass);
|
2017-06-28 02:03:17 +03:00
|
|
|
nsFactoryEntry* f = entry ? entry.Data() : nullptr;
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!f || f->mFactory != aFactory) {
|
|
|
|
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
|
|
|
}
|
2010-06-21 20:46:26 +04:00
|
|
|
|
2017-06-28 02:03:17 +03:00
|
|
|
entry.Remove();
|
2010-06-21 20:46:26 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// This might leave a stale contractid -> factory mapping in
|
|
|
|
// place, so null out the factory entry (see
|
|
|
|
// nsFactoryEntry::GetFactory)
|
|
|
|
f->mFactory.swap(dyingFactory);
|
|
|
|
f->mServiceObject.swap(dyingServiceObject);
|
|
|
|
}
|
2010-06-10 22:11:11 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_OK;
|
2002-01-30 00:22:13 +03:00
|
|
|
}
|
1999-08-09 09:02:25 +04:00
|
|
|
|
2010-06-24 22:31:18 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::AutoRegister(nsIFile* aLocation)
|
|
|
|
{
|
2015-05-01 17:23:44 +03:00
|
|
|
XRE_AddManifestLocation(NS_EXTENSION_LOCATION, aLocation);
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_OK;
|
2010-06-24 22:31:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::AutoUnregister(nsIFile* aLocation)
|
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_ERROR("AutoUnregister not implemented.");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
2010-06-24 22:31:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::RegisterFactoryLocation(const nsCID& aCID,
|
|
|
|
const char* aClassName,
|
|
|
|
const char* aContractID,
|
|
|
|
nsIFile* aFile,
|
|
|
|
const char* aLoaderStr,
|
|
|
|
const char* aType)
|
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_ERROR("RegisterFactoryLocation not implemented.");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
2010-06-24 22:31:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::UnregisterFactoryLocation(const nsCID& aCID,
|
|
|
|
nsIFile* aFile)
|
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_ERROR("UnregisterFactoryLocation not implemented.");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
2010-06-24 22:31:18 +04:00
|
|
|
}
|
|
|
|
|
2003-06-19 03:03:08 +04:00
|
|
|
NS_IMETHODIMP
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::IsCIDRegistered(const nsCID& aClass,
|
|
|
|
bool* aResult)
|
2002-01-30 00:22:13 +03:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
*aResult = (nullptr != GetFactoryEntry(aClass));
|
|
|
|
return NS_OK;
|
2002-01-30 00:22:13 +03:00
|
|
|
}
|
1999-09-05 10:27:42 +04:00
|
|
|
|
2003-06-19 03:03:08 +04:00
|
|
|
NS_IMETHODIMP
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::IsContractIDRegistered(const char* aClass,
|
|
|
|
bool* aResult)
|
2002-01-30 00:22:13 +03:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
if (NS_WARN_IF(!aClass)) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
2013-11-20 01:27:37 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsFactoryEntry* entry = GetFactoryEntry(aClass, strlen(aClass));
|
1999-08-09 09:02:25 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (entry) {
|
2015-10-20 22:06:42 +03:00
|
|
|
// UnregisterFactory might have left a stale nsFactoryEntry in
|
|
|
|
// mContractIDs, so we should check to see whether this entry has
|
|
|
|
// anything useful.
|
|
|
|
*aResult = (bool(entry->mModule) ||
|
|
|
|
bool(entry->mFactory) ||
|
|
|
|
bool(entry->mServiceObject));
|
2014-08-03 00:44:06 +04:00
|
|
|
} else {
|
|
|
|
*aResult = false;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
1999-08-09 09:02:25 +04:00
|
|
|
}
|
|
|
|
|
2003-06-19 03:03:08 +04:00
|
|
|
NS_IMETHODIMP
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::EnumerateCIDs(nsISimpleEnumerator** aEnumerator)
|
1999-08-09 09:02:25 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCOMArray<nsISupports> array;
|
2015-07-10 02:54:59 +03:00
|
|
|
for (auto iter = mFactories.Iter(); !iter.Done(); iter.Next()) {
|
2018-07-22 05:09:25 +03:00
|
|
|
const nsID* id = iter.Key();
|
2016-05-03 23:25:41 +03:00
|
|
|
nsCOMPtr<nsISupportsID> wrapper = new nsSupportsID();
|
2018-07-22 05:09:25 +03:00
|
|
|
wrapper->SetData(id);
|
2015-07-10 02:54:59 +03:00
|
|
|
array.AppendObject(wrapper);
|
|
|
|
}
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_NewArrayEnumerator(aEnumerator, array);
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
1999-08-09 09:02:25 +04:00
|
|
|
|
2003-06-19 03:03:08 +04:00
|
|
|
NS_IMETHODIMP
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::EnumerateContractIDs(nsISimpleEnumerator** aEnumerator)
|
1999-08-09 09:02:25 +04:00
|
|
|
{
|
2016-11-16 15:24:59 +03:00
|
|
|
auto* array = new nsTArray<nsCString>;
|
2015-07-10 02:54:59 +03:00
|
|
|
for (auto iter = mContractIDs.Iter(); !iter.Done(); iter.Next()) {
|
2015-07-20 15:21:28 +03:00
|
|
|
const nsACString& contract = iter.Key();
|
2015-07-10 02:54:59 +03:00
|
|
|
array->AppendElement(contract);
|
|
|
|
}
|
1999-08-09 09:02:25 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCOMPtr<nsIUTF8StringEnumerator> e;
|
|
|
|
nsresult rv = NS_NewAdoptingUTF8StringEnumerator(getter_AddRefs(e), array);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
1999-08-09 09:02:25 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return CallQueryInterface(e, aEnumerator);
|
2002-01-30 00:22:13 +03:00
|
|
|
}
|
2000-01-12 01:54:46 +03:00
|
|
|
|
2003-06-19 03:03:08 +04:00
|
|
|
NS_IMETHODIMP
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::CIDToContractID(const nsCID& aClass,
|
|
|
|
char** aResult)
|
2000-01-12 01:54:46 +03:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_ERROR("CIDTOContractID not implemented");
|
|
|
|
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
2000-01-12 01:54:46 +03:00
|
|
|
}
|
|
|
|
|
2003-06-19 03:03:08 +04:00
|
|
|
NS_IMETHODIMP
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::ContractIDToCID(const char* aContractID,
|
|
|
|
nsCID** aResult)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
SafeMutexAutoLock lock(mLock);
|
|
|
|
nsFactoryEntry* entry = mContractIDs.Get(nsDependentCString(aContractID));
|
|
|
|
if (entry) {
|
2015-04-01 08:29:55 +03:00
|
|
|
*aResult = (nsCID*)moz_xmalloc(sizeof(nsCID));
|
2014-08-03 00:44:06 +04:00
|
|
|
**aResult = *entry->mCIDEntry->cid;
|
|
|
|
return NS_OK;
|
2002-04-08 04:18:14 +04:00
|
|
|
}
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
|
|
|
*aResult = nullptr;
|
|
|
|
return NS_ERROR_FACTORY_NOT_REGISTERED;
|
2001-08-30 18:10:41 +04:00
|
|
|
}
|
|
|
|
|
2013-12-08 10:09:10 +04:00
|
|
|
MOZ_DEFINE_MALLOC_SIZE_OF(ComponentManagerMallocSizeOf)
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsComponentManagerImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
|
2014-05-21 10:06:54 +04:00
|
|
|
nsISupports* aData, bool aAnonymize)
|
2013-11-07 09:35:30 +04:00
|
|
|
{
|
2016-08-24 08:23:45 +03:00
|
|
|
MOZ_COLLECT_REPORT(
|
|
|
|
"explicit/xpcom/component-manager", KIND_HEAP, UNITS_BYTES,
|
|
|
|
SizeOfIncludingThis(ComponentManagerMallocSizeOf),
|
|
|
|
"Memory used for the XPCOM component manager.");
|
|
|
|
|
|
|
|
return NS_OK;
|
2013-11-07 09:35:30 +04:00
|
|
|
}
|
|
|
|
|
2012-10-19 16:07:36 +04:00
|
|
|
size_t
|
2013-11-07 09:35:30 +04:00
|
|
|
nsComponentManagerImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
|
2015-07-31 07:19:57 +03:00
|
|
|
const
|
2012-10-19 16:07:36 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
size_t n = aMallocSizeOf(this);
|
2015-07-31 07:19:57 +03:00
|
|
|
|
|
|
|
n += mFactories.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
for (auto iter = mFactories.ConstIter(); !iter.Done(); iter.Next()) {
|
|
|
|
n += iter.Data()->SizeOfIncludingThis(aMallocSizeOf);
|
|
|
|
}
|
|
|
|
|
|
|
|
n += mContractIDs.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
for (auto iter = mContractIDs.ConstIter(); !iter.Done(); iter.Next()) {
|
|
|
|
// We don't measure the nsFactoryEntry data because it's owned by
|
|
|
|
// mFactories (which is measured above).
|
2015-12-02 02:36:26 +03:00
|
|
|
n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
2015-07-31 07:19:57 +03:00
|
|
|
}
|
2012-10-19 16:07:36 +04:00
|
|
|
|
2018-06-26 10:10:30 +03:00
|
|
|
n += sExtraStaticModules->ShallowSizeOfIncludingThis(aMallocSizeOf);
|
2017-01-27 03:35:54 +03:00
|
|
|
if (sModuleLocations) {
|
|
|
|
n += sModuleLocations->ShallowSizeOfIncludingThis(aMallocSizeOf);
|
|
|
|
}
|
2012-10-19 16:07:36 +04:00
|
|
|
|
2015-07-29 09:24:24 +03:00
|
|
|
n += mKnownStaticModules.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
2015-07-31 07:19:57 +03:00
|
|
|
n += mKnownModules.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
2012-10-19 16:07:36 +04:00
|
|
|
|
2017-03-31 02:46:58 +03:00
|
|
|
n += mArena.SizeOfExcludingThis(aMallocSizeOf);
|
2012-10-19 16:07:36 +04:00
|
|
|
|
2015-07-29 09:24:24 +03:00
|
|
|
n += mPendingServices.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
2012-10-19 16:07:36 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// Measurement of the following members may be added later if DMD finds it is
|
|
|
|
// worthwhile:
|
|
|
|
// - mMon
|
|
|
|
// - sModuleLocations' entries
|
|
|
|
// - mKnownStaticModules' entries?
|
|
|
|
// - mKnownModules' keys and values?
|
2012-10-19 16:07:36 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return n;
|
2012-10-19 16:07:36 +04:00
|
|
|
}
|
|
|
|
|
2005-12-13 20:55:43 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// nsFactoryEntry
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2001-08-30 18:10:41 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsFactoryEntry::nsFactoryEntry(const mozilla::Module::CIDEntry* aEntry,
|
|
|
|
nsComponentManagerImpl::KnownModule* aModule)
|
|
|
|
: mCIDEntry(aEntry)
|
|
|
|
, mModule(aModule)
|
2002-06-15 01:33:05 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
nsFactoryEntry::nsFactoryEntry(const nsCID& aCID, nsIFactory* aFactory)
|
|
|
|
: mCIDEntry(nullptr)
|
|
|
|
, mModule(nullptr)
|
|
|
|
, mFactory(aFactory)
|
2002-06-15 01:33:05 +04:00
|
|
|
{
|
2016-11-16 15:24:59 +03:00
|
|
|
auto* e = new mozilla::Module::CIDEntry();
|
|
|
|
auto* cid = new nsCID;
|
2014-08-03 00:44:06 +04:00
|
|
|
*cid = aCID;
|
|
|
|
e->cid = cid;
|
|
|
|
mCIDEntry = e;
|
2013-06-14 07:57:47 +04:00
|
|
|
}
|
2002-06-15 01:33:05 +04:00
|
|
|
|
2010-06-25 18:44:35 +04:00
|
|
|
nsFactoryEntry::~nsFactoryEntry()
|
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
// If this was a RegisterFactory entry, we own the CIDEntry/CID
|
|
|
|
if (!mModule) {
|
|
|
|
delete mCIDEntry->cid;
|
|
|
|
delete mCIDEntry;
|
|
|
|
}
|
2010-06-25 18:44:35 +04:00
|
|
|
}
|
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
already_AddRefed<nsIFactory>
|
|
|
|
nsFactoryEntry::GetFactory()
|
2002-06-15 01:33:05 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::gComponentManager->mLock.AssertNotCurrentThreadOwns();
|
|
|
|
|
|
|
|
if (!mFactory) {
|
|
|
|
// RegisterFactory then UnregisterFactory can leave an entry in mContractIDs
|
|
|
|
// pointing to an unusable nsFactoryEntry.
|
|
|
|
if (!mModule) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mModule->Load()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't set mFactory directly, it needs to be locked
|
|
|
|
nsCOMPtr<nsIFactory> factory;
|
2013-03-14 00:39:28 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (mModule->Module()->getFactoryProc) {
|
|
|
|
factory = mModule->Module()->getFactoryProc(*mModule->Module(),
|
|
|
|
*mCIDEntry);
|
|
|
|
} else if (mCIDEntry->getFactoryProc) {
|
|
|
|
factory = mCIDEntry->getFactoryProc(*mModule->Module(), *mCIDEntry);
|
|
|
|
} else {
|
|
|
|
NS_ASSERTION(mCIDEntry->constructorProc, "no getfactory or constructor");
|
|
|
|
factory = new mozilla::GenericFactory(mCIDEntry->constructorProc);
|
|
|
|
}
|
|
|
|
if (!factory) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
SafeMutexAutoLock lock(nsComponentManagerImpl::gComponentManager->mLock);
|
|
|
|
// Threads can race to set mFactory
|
2005-12-13 20:55:43 +03:00
|
|
|
if (!mFactory) {
|
2014-08-03 00:44:06 +04:00
|
|
|
factory.swap(mFactory);
|
2003-03-05 06:22:12 +03:00
|
|
|
}
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
|
|
|
nsCOMPtr<nsIFactory> factory = mFactory;
|
|
|
|
return factory.forget();
|
2002-06-15 01:33:05 +04:00
|
|
|
}
|
|
|
|
|
2012-10-19 16:07:36 +04:00
|
|
|
size_t
|
2013-06-23 16:03:39 +04:00
|
|
|
nsFactoryEntry::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
|
2012-10-19 16:07:36 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
size_t n = aMallocSizeOf(this);
|
2012-10-19 16:07:36 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
// Measurement of the following members may be added later if DMD finds it is
|
|
|
|
// worthwhile:
|
|
|
|
// - mCIDEntry;
|
|
|
|
// - mModule;
|
|
|
|
// - mFactory;
|
|
|
|
// - mServiceObject;
|
2012-10-19 16:07:36 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return n;
|
2012-10-19 16:07:36 +04:00
|
|
|
}
|
|
|
|
|
2002-01-30 00:22:13 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Static Access Functions
|
1999-03-09 12:44:27 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2011-08-18 17:46:39 +04:00
|
|
|
nsresult
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_GetComponentManager(nsIComponentManager** aResult)
|
2001-10-16 07:35:52 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!nsComponentManagerImpl::gComponentManager) {
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
}
|
2001-10-16 07:35:52 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
|
|
|
|
return NS_OK;
|
2001-10-16 07:35:52 +04:00
|
|
|
}
|
|
|
|
|
2011-08-18 17:46:39 +04:00
|
|
|
nsresult
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_GetServiceManager(nsIServiceManager** aResult)
|
2001-09-07 01:13:11 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!nsComponentManagerImpl::gComponentManager) {
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
}
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
|
|
|
|
return NS_OK;
|
2001-09-07 01:13:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-08-18 17:46:39 +04:00
|
|
|
nsresult
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_GetComponentRegistrar(nsIComponentRegistrar** aResult)
|
2002-01-30 00:22:13 +03:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!nsComponentManagerImpl::gComponentManager) {
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
}
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
|
|
|
|
return NS_OK;
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
2002-01-30 00:22:13 +03:00
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
EXPORT_XPCOM_API(nsresult)
|
|
|
|
XRE_AddStaticComponent(const mozilla::Module* aComponent)
|
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::InitializeStaticModules();
|
2018-06-26 10:10:30 +03:00
|
|
|
sExtraStaticModules->AppendElement(aComponent);
|
2010-06-10 22:11:11 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (nsComponentManagerImpl::gComponentManager &&
|
|
|
|
nsComponentManagerImpl::NORMAL ==
|
|
|
|
nsComponentManagerImpl::gComponentManager->mStatus) {
|
2018-10-23 03:47:24 +03:00
|
|
|
nsComponentManagerImpl::gComponentManager->RegisterModule(aComponent);
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
2010-06-10 22:11:11 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_OK;
|
2010-06-10 22:11:11 +04:00
|
|
|
}
|
|
|
|
|
2011-07-29 13:20:47 +04:00
|
|
|
NS_IMETHODIMP
|
2012-06-06 06:08:30 +04:00
|
|
|
nsComponentManagerImpl::AddBootstrappedManifestLocation(nsIFile* aLocation)
|
2011-07-29 13:20:47 +04:00
|
|
|
{
|
|
|
|
nsString path;
|
|
|
|
nsresult rv = aLocation->GetPath(path);
|
2014-08-03 00:44:06 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
2011-07-29 13:20:47 +04:00
|
|
|
return rv;
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
2011-07-29 13:20:47 +04:00
|
|
|
|
2014-05-22 07:48:51 +04:00
|
|
|
if (Substring(path, path.Length() - 4).EqualsLiteral(".xpi")) {
|
2011-07-29 13:20:47 +04:00
|
|
|
return XRE_AddJarManifestLocation(NS_BOOTSTRAPPED_LOCATION, aLocation);
|
|
|
|
}
|
|
|
|
|
2012-06-06 06:08:30 +04:00
|
|
|
nsCOMPtr<nsIFile> manifest =
|
2011-07-29 13:20:47 +04:00
|
|
|
CloneAndAppend(aLocation, NS_LITERAL_CSTRING("chrome.manifest"));
|
|
|
|
return XRE_AddManifestLocation(NS_BOOTSTRAPPED_LOCATION, manifest);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-06-06 06:08:30 +04:00
|
|
|
nsComponentManagerImpl::RemoveBootstrappedManifestLocation(nsIFile* aLocation)
|
2011-07-29 13:20:47 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIChromeRegistry> cr = mozilla::services::GetChromeRegistryService();
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!cr) {
|
2011-07-29 13:20:47 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
2011-07-29 13:20:47 +04:00
|
|
|
|
|
|
|
nsString path;
|
|
|
|
nsresult rv = aLocation->GetPath(path);
|
2014-08-03 00:44:06 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
2011-07-29 13:20:47 +04:00
|
|
|
return rv;
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
2011-07-29 13:20:47 +04:00
|
|
|
|
2011-11-08 21:10:51 +04:00
|
|
|
nsComponentManagerImpl::ComponentLocation elem;
|
|
|
|
elem.type = NS_BOOTSTRAPPED_LOCATION;
|
|
|
|
|
2014-05-22 07:48:51 +04:00
|
|
|
if (Substring(path, path.Length() - 4).EqualsLiteral(".xpi")) {
|
2011-11-08 21:10:51 +04:00
|
|
|
elem.location.Init(aLocation, "chrome.manifest");
|
2011-07-29 13:20:47 +04:00
|
|
|
} else {
|
2014-08-03 00:44:06 +04:00
|
|
|
nsCOMPtr<nsIFile> lf =
|
|
|
|
CloneAndAppend(aLocation, NS_LITERAL_CSTRING("chrome.manifest"));
|
2011-11-08 21:10:51 +04:00
|
|
|
elem.location.Init(lf);
|
2011-07-29 13:20:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Remove reference.
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::sModuleLocations->RemoveElement(elem,
|
|
|
|
ComponentLocationComparator());
|
2011-07-29 13:20:47 +04:00
|
|
|
|
|
|
|
rv = cr->CheckForNewChrome();
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2013-07-05 23:20:04 +04:00
|
|
|
NS_IMETHODIMP
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::GetManifestLocations(nsIArray** aLocations)
|
2013-07-05 23:20:04 +04:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aLocations);
|
|
|
|
*aLocations = nullptr;
|
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (!sModuleLocations) {
|
2013-07-05 23:20:04 +04:00
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
2013-07-05 23:20:04 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIMutableArray> locations = nsArray::Create();
|
|
|
|
nsresult rv;
|
|
|
|
for (uint32_t i = 0; i < sModuleLocations->Length(); ++i) {
|
|
|
|
ComponentLocation& l = sModuleLocations->ElementAt(i);
|
|
|
|
FileLocation loc = l.location;
|
|
|
|
nsCString uriString;
|
|
|
|
loc.GetURIString(uriString);
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
rv = NS_NewURI(getter_AddRefs(uri), uriString);
|
2014-08-03 00:44:06 +04:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2017-10-21 17:53:02 +03:00
|
|
|
locations->AppendElement(uri);
|
2014-08-03 00:44:06 +04:00
|
|
|
}
|
2013-07-05 23:20:04 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
locations.forget(aLocations);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-06-10 22:11:11 +04:00
|
|
|
EXPORT_XPCOM_API(nsresult)
|
2012-06-06 06:08:30 +04:00
|
|
|
XRE_AddManifestLocation(NSLocationType aType, nsIFile* aLocation)
|
2010-06-10 22:11:11 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::InitializeModuleLocations();
|
|
|
|
nsComponentManagerImpl::ComponentLocation* c =
|
|
|
|
nsComponentManagerImpl::sModuleLocations->AppendElement();
|
|
|
|
c->type = aType;
|
|
|
|
c->location.Init(aLocation);
|
|
|
|
|
|
|
|
if (nsComponentManagerImpl::gComponentManager &&
|
|
|
|
nsComponentManagerImpl::NORMAL ==
|
|
|
|
nsComponentManagerImpl::gComponentManager->mStatus) {
|
|
|
|
nsComponentManagerImpl::gComponentManager->RegisterManifest(aType,
|
|
|
|
c->location,
|
|
|
|
false);
|
|
|
|
}
|
2002-10-06 03:59:57 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_OK;
|
2002-01-30 00:22:13 +03:00
|
|
|
}
|
2010-09-09 07:37:11 +04:00
|
|
|
|
|
|
|
EXPORT_XPCOM_API(nsresult)
|
2012-06-06 06:08:30 +04:00
|
|
|
XRE_AddJarManifestLocation(NSLocationType aType, nsIFile* aLocation)
|
2010-09-09 07:37:11 +04:00
|
|
|
{
|
2014-08-03 00:44:06 +04:00
|
|
|
nsComponentManagerImpl::InitializeModuleLocations();
|
|
|
|
nsComponentManagerImpl::ComponentLocation* c =
|
|
|
|
nsComponentManagerImpl::sModuleLocations->AppendElement();
|
2010-09-09 07:37:11 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
c->type = aType;
|
|
|
|
c->location.Init(aLocation, "chrome.manifest");
|
2010-09-09 07:37:11 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
if (nsComponentManagerImpl::gComponentManager &&
|
|
|
|
nsComponentManagerImpl::NORMAL ==
|
|
|
|
nsComponentManagerImpl::gComponentManager->mStatus) {
|
|
|
|
nsComponentManagerImpl::gComponentManager->RegisterManifest(aType,
|
|
|
|
c->location,
|
|
|
|
false);
|
|
|
|
}
|
2010-09-09 07:37:11 +04:00
|
|
|
|
2014-08-03 00:44:06 +04:00
|
|
|
return NS_OK;
|
2010-09-09 07:37:11 +04:00
|
|
|
}
|
|
|
|
|
2018-01-05 01:37:39 +03:00
|
|
|
// Expose some important global interfaces to rust for the rust xpcom API. These
|
|
|
|
// methods return a non-owning reference to the component manager, which should
|
|
|
|
// live for the lifetime of XPCOM.
|
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
const nsIComponentManager*
|
|
|
|
Gecko_GetComponentManager()
|
|
|
|
{
|
|
|
|
return nsComponentManagerImpl::gComponentManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
const nsIServiceManager*
|
|
|
|
Gecko_GetServiceManager()
|
|
|
|
{
|
|
|
|
return nsComponentManagerImpl::gComponentManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
const nsIComponentRegistrar*
|
|
|
|
Gecko_GetComponentRegistrar()
|
|
|
|
{
|
|
|
|
return nsComponentManagerImpl::gComponentManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|