1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/components/nsComponentManager.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1972 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* vim: set ts=8 sts=4 et sw=4 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.9 + * 1.10 + * This Original Code has been modified by IBM Corporation. 1.11 + * Modifications made by IBM described herein are 1.12 + * Copyright (c) International Business Machines 1.13 + * Corporation, 2000 1.14 + * 1.15 + * Modifications to Mozilla code or documentation 1.16 + * identified per MPL Section 3.3 1.17 + * 1.18 + * Date Modified by Description of modification 1.19 + * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2 1.20 + */ 1.21 + 1.22 +#include <stdlib.h> 1.23 +#include "nscore.h" 1.24 +#include "nsISupports.h" 1.25 +#include "nspr.h" 1.26 +#include "nsCRT.h" // for atoll 1.27 + 1.28 +// Arena used by component manager for storing contractid string, dll 1.29 +// location strings and small objects 1.30 +// CAUTION: Arena align mask needs to be defined before including plarena.h 1.31 +// currently from nsComponentManager.h 1.32 +#define PL_ARENA_CONST_ALIGN_MASK 7 1.33 +#define NS_CM_BLOCK_SIZE (1024 * 8) 1.34 + 1.35 +#include "nsCategoryManager.h" 1.36 +#include "nsCOMPtr.h" 1.37 +#include "nsComponentManager.h" 1.38 +#include "nsDirectoryService.h" 1.39 +#include "nsDirectoryServiceDefs.h" 1.40 +#include "nsCategoryManager.h" 1.41 +#include "nsCategoryManagerUtils.h" 1.42 +#include "xptiprivate.h" 1.43 +#include "mozilla/MemoryReporting.h" 1.44 +#include "mozilla/XPTInterfaceInfoManager.h" 1.45 +#include "nsIConsoleService.h" 1.46 +#include "nsIObserverService.h" 1.47 +#include "nsISimpleEnumerator.h" 1.48 +#include "nsIStringEnumerator.h" 1.49 +#include "nsXPCOM.h" 1.50 +#include "nsXPCOMPrivate.h" 1.51 +#include "nsISupportsPrimitives.h" 1.52 +#include "nsIClassInfo.h" 1.53 +#include "nsLocalFile.h" 1.54 +#include "nsReadableUtils.h" 1.55 +#include "nsString.h" 1.56 +#include "nsXPIDLString.h" 1.57 +#include "prcmon.h" 1.58 +#include "xptinfo.h" // this after nsISupports, to pick up IID so that xpt stuff doesn't try to define it itself... 1.59 +#include "nsThreadUtils.h" 1.60 +#include "prthread.h" 1.61 +#include "private/pprthred.h" 1.62 +#include "nsTArray.h" 1.63 +#include "prio.h" 1.64 +#include "ManifestParser.h" 1.65 +#include "mozilla/Services.h" 1.66 + 1.67 +#include "nsManifestLineReader.h" 1.68 +#include "mozilla/GenericFactory.h" 1.69 +#include "nsSupportsPrimitives.h" 1.70 +#include "nsArray.h" 1.71 +#include "nsIMutableArray.h" 1.72 +#include "nsArrayEnumerator.h" 1.73 +#include "nsStringEnumerator.h" 1.74 +#include "mozilla/FileUtils.h" 1.75 +#include "nsNetUtil.h" 1.76 + 1.77 +#include <new> // for placement new 1.78 + 1.79 +#include "mozilla/Omnijar.h" 1.80 + 1.81 +#include "prlog.h" 1.82 + 1.83 +using namespace mozilla; 1.84 + 1.85 +PRLogModuleInfo* nsComponentManagerLog = nullptr; 1.86 + 1.87 +// defined in nsStaticXULComponents.cpp to contain all the components in 1.88 +// libxul. 1.89 +extern mozilla::Module const *const *const kPStaticModules[]; 1.90 + 1.91 +#if 0 || defined (DEBUG_timeless) 1.92 + #define SHOW_DENIED_ON_SHUTDOWN 1.93 + #define SHOW_CI_ON_EXISTING_SERVICE 1.94 +#endif 1.95 + 1.96 +// Bloated registry buffer size to improve startup performance -- needs to 1.97 +// be big enough to fit the entire file into memory or it'll thrash. 1.98 +// 512K is big enough to allow for some future growth in the registry. 1.99 +#define BIG_REGISTRY_BUFLEN (512*1024) 1.100 + 1.101 +// Common Key Names 1.102 +const char xpcomComponentsKeyName[]="software/mozilla/XPCOM/components"; 1.103 +const char xpcomKeyName[]="software/mozilla/XPCOM"; 1.104 + 1.105 +// Common Value Names 1.106 +const char fileSizeValueName[]="FileSize"; 1.107 +const char lastModValueName[]="LastModTimeStamp"; 1.108 +const char nativeComponentType[]="application/x-mozilla-native"; 1.109 +const char staticComponentType[]="application/x-mozilla-static"; 1.110 + 1.111 +NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID); 1.112 + 1.113 +#define UID_STRING_LENGTH 39 1.114 + 1.115 +nsresult 1.116 +nsGetServiceFromCategory::operator()(const nsIID& aIID, void** aInstancePtr) const 1.117 +{ 1.118 + nsresult rv; 1.119 + nsXPIDLCString value; 1.120 + nsCOMPtr<nsICategoryManager> catman; 1.121 + nsComponentManagerImpl *compMgr = nsComponentManagerImpl::gComponentManager; 1.122 + if (!compMgr) { 1.123 + rv = NS_ERROR_NOT_INITIALIZED; 1.124 + goto error; 1.125 + } 1.126 + 1.127 + if (!mCategory || !mEntry) { 1.128 + // when categories have defaults, use that for null mEntry 1.129 + rv = NS_ERROR_NULL_POINTER; 1.130 + goto error; 1.131 + } 1.132 + 1.133 + rv = compMgr->nsComponentManagerImpl::GetService(kCategoryManagerCID, 1.134 + NS_GET_IID(nsICategoryManager), 1.135 + getter_AddRefs(catman)); 1.136 + if (NS_FAILED(rv)) goto error; 1.137 + 1.138 + /* find the contractID for category.entry */ 1.139 + rv = catman->GetCategoryEntry(mCategory, mEntry, 1.140 + getter_Copies(value)); 1.141 + if (NS_FAILED(rv)) goto error; 1.142 + if (!value) { 1.143 + rv = NS_ERROR_SERVICE_NOT_AVAILABLE; 1.144 + goto error; 1.145 + } 1.146 + 1.147 + rv = compMgr-> 1.148 + nsComponentManagerImpl::GetServiceByContractID(value, 1.149 + aIID, aInstancePtr); 1.150 + if (NS_FAILED(rv)) { 1.151 + error: 1.152 + *aInstancePtr = 0; 1.153 + } 1.154 + if (mErrorPtr) 1.155 + *mErrorPtr = rv; 1.156 + return rv; 1.157 +} 1.158 + 1.159 +//////////////////////////////////////////////////////////////////////////////// 1.160 +// Arena helper functions 1.161 +//////////////////////////////////////////////////////////////////////////////// 1.162 +char * 1.163 +ArenaStrndup(const char *s, uint32_t len, PLArenaPool *arena) 1.164 +{ 1.165 + void *mem; 1.166 + // Include trailing null in the len 1.167 + PL_ARENA_ALLOCATE(mem, arena, len+1); 1.168 + if (mem) 1.169 + memcpy(mem, s, len+1); 1.170 + return static_cast<char *>(mem); 1.171 +} 1.172 + 1.173 +char* 1.174 +ArenaStrdup(const char *s, PLArenaPool *arena) 1.175 +{ 1.176 + return ArenaStrndup(s, strlen(s), arena); 1.177 +} 1.178 + 1.179 +// GetService and a few other functions need to exit their mutex mid-function 1.180 +// without reentering it later in the block. This class supports that 1.181 +// style of early-exit that MutexAutoUnlock doesn't. 1.182 + 1.183 +namespace { 1.184 + 1.185 +class MOZ_STACK_CLASS MutexLock 1.186 +{ 1.187 +public: 1.188 + MutexLock(SafeMutex& aMutex) 1.189 + : mMutex(aMutex) 1.190 + , mLocked(false) 1.191 + { 1.192 + Lock(); 1.193 + } 1.194 + 1.195 + ~MutexLock() 1.196 + { 1.197 + if (mLocked) 1.198 + Unlock(); 1.199 + } 1.200 + 1.201 + void Lock() 1.202 + { 1.203 + NS_ASSERTION(!mLocked, "Re-entering a mutex"); 1.204 + mMutex.Lock(); 1.205 + mLocked = true; 1.206 + } 1.207 + 1.208 + void Unlock() 1.209 + { 1.210 + NS_ASSERTION(mLocked, "Exiting a mutex that isn't held!"); 1.211 + mMutex.Unlock(); 1.212 + mLocked = false; 1.213 + } 1.214 + 1.215 +private: 1.216 + SafeMutex& mMutex; 1.217 + bool mLocked; 1.218 +}; 1.219 + 1.220 +} // anonymous namespace 1.221 + 1.222 +// this is safe to call during InitXPCOM 1.223 +static already_AddRefed<nsIFile> 1.224 +GetLocationFromDirectoryService(const char* prop) 1.225 +{ 1.226 + nsCOMPtr<nsIProperties> directoryService; 1.227 + nsDirectoryService::Create(nullptr, 1.228 + NS_GET_IID(nsIProperties), 1.229 + getter_AddRefs(directoryService)); 1.230 + 1.231 + if (!directoryService) 1.232 + return nullptr; 1.233 + 1.234 + nsCOMPtr<nsIFile> file; 1.235 + nsresult rv = directoryService->Get(prop, 1.236 + NS_GET_IID(nsIFile), 1.237 + getter_AddRefs(file)); 1.238 + if (NS_FAILED(rv)) 1.239 + return nullptr; 1.240 + 1.241 + return file.forget(); 1.242 +} 1.243 + 1.244 +static already_AddRefed<nsIFile> 1.245 +CloneAndAppend(nsIFile* aBase, const nsACString& append) 1.246 +{ 1.247 + nsCOMPtr<nsIFile> f; 1.248 + aBase->Clone(getter_AddRefs(f)); 1.249 + if (!f) 1.250 + return nullptr; 1.251 + 1.252 + f->AppendNative(append); 1.253 + return f.forget(); 1.254 +} 1.255 + 1.256 +//////////////////////////////////////////////////////////////////////////////// 1.257 +// nsComponentManagerImpl 1.258 +//////////////////////////////////////////////////////////////////////////////// 1.259 + 1.260 +nsresult 1.261 +nsComponentManagerImpl::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult) 1.262 +{ 1.263 + if (aOuter) 1.264 + return NS_ERROR_NO_AGGREGATION; 1.265 + 1.266 + if (!gComponentManager) 1.267 + return NS_ERROR_FAILURE; 1.268 + 1.269 + return gComponentManager->QueryInterface(aIID, aResult); 1.270 +} 1.271 + 1.272 +static const int CONTRACTID_HASHTABLE_INITIAL_SIZE = 2048; 1.273 + 1.274 +nsComponentManagerImpl::nsComponentManagerImpl() 1.275 + : mFactories(CONTRACTID_HASHTABLE_INITIAL_SIZE) 1.276 + , mContractIDs(CONTRACTID_HASHTABLE_INITIAL_SIZE) 1.277 + , mLock("nsComponentManagerImpl.mLock") 1.278 + , mStatus(NOT_INITIALIZED) 1.279 +{ 1.280 +} 1.281 + 1.282 +nsTArray<const mozilla::Module*>* nsComponentManagerImpl::sStaticModules; 1.283 + 1.284 +/* static */ void 1.285 +nsComponentManagerImpl::InitializeStaticModules() 1.286 +{ 1.287 + if (sStaticModules) 1.288 + return; 1.289 + 1.290 + sStaticModules = new nsTArray<const mozilla::Module*>; 1.291 + for (const mozilla::Module *const *const *staticModules = kPStaticModules; 1.292 + *staticModules; ++staticModules) 1.293 + sStaticModules->AppendElement(**staticModules); 1.294 +} 1.295 + 1.296 +nsTArray<nsComponentManagerImpl::ComponentLocation>* 1.297 +nsComponentManagerImpl::sModuleLocations; 1.298 + 1.299 +/* static */ void 1.300 +nsComponentManagerImpl::InitializeModuleLocations() 1.301 +{ 1.302 + if (sModuleLocations) 1.303 + return; 1.304 + 1.305 + sModuleLocations = new nsTArray<ComponentLocation>; 1.306 +} 1.307 + 1.308 +nsresult nsComponentManagerImpl::Init() 1.309 +{ 1.310 + PR_ASSERT(NOT_INITIALIZED == mStatus); 1.311 + 1.312 + if (nsComponentManagerLog == nullptr) 1.313 + { 1.314 + nsComponentManagerLog = PR_NewLogModule("nsComponentManager"); 1.315 + } 1.316 + 1.317 + // Initialize our arena 1.318 + PL_INIT_ARENA_POOL(&mArena, "ComponentManagerArena", NS_CM_BLOCK_SIZE); 1.319 + 1.320 + nsCOMPtr<nsIFile> greDir = 1.321 + GetLocationFromDirectoryService(NS_GRE_DIR); 1.322 + nsCOMPtr<nsIFile> appDir = 1.323 + GetLocationFromDirectoryService(NS_XPCOM_CURRENT_PROCESS_DIR); 1.324 + 1.325 + InitializeStaticModules(); 1.326 + InitializeModuleLocations(); 1.327 + 1.328 + ComponentLocation* cl = sModuleLocations->InsertElementAt(0); 1.329 + nsCOMPtr<nsIFile> lf = CloneAndAppend(appDir, NS_LITERAL_CSTRING("chrome.manifest")); 1.330 + cl->type = NS_COMPONENT_LOCATION; 1.331 + cl->location.Init(lf); 1.332 + 1.333 + bool equals = false; 1.334 + appDir->Equals(greDir, &equals); 1.335 + if (!equals) { 1.336 + cl = sModuleLocations->InsertElementAt(0); 1.337 + cl->type = NS_COMPONENT_LOCATION; 1.338 + lf = CloneAndAppend(greDir, NS_LITERAL_CSTRING("chrome.manifest")); 1.339 + cl->location.Init(lf); 1.340 + } 1.341 + 1.342 + PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, 1.343 + ("nsComponentManager: Initialized.")); 1.344 + 1.345 + nsresult rv = mNativeModuleLoader.Init(); 1.346 + if (NS_FAILED(rv)) 1.347 + return rv; 1.348 + 1.349 + nsCategoryManager::GetSingleton()->SuppressNotifications(true); 1.350 + 1.351 + RegisterModule(&kXPCOMModule, nullptr); 1.352 + 1.353 + for (uint32_t i = 0; i < sStaticModules->Length(); ++i) 1.354 + RegisterModule((*sStaticModules)[i], nullptr); 1.355 + 1.356 + nsRefPtr<nsZipArchive> appOmnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP); 1.357 + if (appOmnijar) { 1.358 + cl = sModuleLocations->InsertElementAt(1); // Insert after greDir 1.359 + cl->type = NS_COMPONENT_LOCATION; 1.360 + cl->location.Init(appOmnijar, "chrome.manifest"); 1.361 + } 1.362 + nsRefPtr<nsZipArchive> greOmnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE); 1.363 + if (greOmnijar) { 1.364 + cl = sModuleLocations->InsertElementAt(0); 1.365 + cl->type = NS_COMPONENT_LOCATION; 1.366 + cl->location.Init(greOmnijar, "chrome.manifest"); 1.367 + } 1.368 + 1.369 + RereadChromeManifests(false); 1.370 + 1.371 + nsCategoryManager::GetSingleton()->SuppressNotifications(false); 1.372 + 1.373 + RegisterWeakMemoryReporter(this); 1.374 + 1.375 + // Unfortunately, we can't register the nsCategoryManager memory reporter 1.376 + // in its constructor (which is triggered by the GetSingleton() call 1.377 + // above) because the memory reporter manager isn't initialized at that 1.378 + // point. So we wait until now. 1.379 + nsCategoryManager::GetSingleton()->InitMemoryReporter(); 1.380 + 1.381 + mStatus = NORMAL; 1.382 + 1.383 + return NS_OK; 1.384 +} 1.385 + 1.386 +void 1.387 +nsComponentManagerImpl::RegisterModule(const mozilla::Module* aModule, 1.388 + FileLocation* aFile) 1.389 +{ 1.390 + mLock.AssertNotCurrentThreadOwns(); 1.391 + 1.392 + { 1.393 + // Scope the monitor so that we don't hold it while calling into the 1.394 + // category manager. 1.395 + MutexLock lock(mLock); 1.396 + 1.397 + KnownModule* m; 1.398 + if (aFile) { 1.399 + nsCString uri; 1.400 + aFile->GetURIString(uri); 1.401 + NS_ASSERTION(!mKnownModules.Get(uri), 1.402 + "Must not register a binary module twice."); 1.403 + 1.404 + m = new KnownModule(aModule, *aFile); 1.405 + mKnownModules.Put(uri, m); 1.406 + } else { 1.407 + m = new KnownModule(aModule); 1.408 + mKnownStaticModules.AppendElement(m); 1.409 + } 1.410 + 1.411 + if (aModule->mCIDs) { 1.412 + const mozilla::Module::CIDEntry* entry; 1.413 + for (entry = aModule->mCIDs; entry->cid; ++entry) 1.414 + RegisterCIDEntryLocked(entry, m); 1.415 + } 1.416 + 1.417 + if (aModule->mContractIDs) { 1.418 + const mozilla::Module::ContractIDEntry* entry; 1.419 + for (entry = aModule->mContractIDs; entry->contractid; ++entry) 1.420 + RegisterContractIDLocked(entry); 1.421 + MOZ_ASSERT(!entry->cid, "Incorrectly terminated contract list"); 1.422 + } 1.423 + } 1.424 + 1.425 + if (aModule->mCategoryEntries) { 1.426 + const mozilla::Module::CategoryEntry* entry; 1.427 + for (entry = aModule->mCategoryEntries; entry->category; ++entry) 1.428 + nsCategoryManager::GetSingleton()-> 1.429 + AddCategoryEntry(entry->category, 1.430 + entry->entry, 1.431 + entry->value); 1.432 + } 1.433 +} 1.434 + 1.435 +static bool 1.436 +ProcessSelectorMatches(Module::ProcessSelector selector) 1.437 +{ 1.438 + if (selector == Module::ANY_PROCESS) { 1.439 + return true; 1.440 + } 1.441 + 1.442 + GeckoProcessType type = XRE_GetProcessType(); 1.443 + switch (selector) { 1.444 + case Module::MAIN_PROCESS_ONLY: 1.445 + return type == GeckoProcessType_Default; 1.446 + case Module::CONTENT_PROCESS_ONLY: 1.447 + return type == GeckoProcessType_Content; 1.448 + default: 1.449 + MOZ_CRASH("invalid process selector"); 1.450 + } 1.451 +} 1.452 + 1.453 +void 1.454 +nsComponentManagerImpl::RegisterCIDEntryLocked( 1.455 + const mozilla::Module::CIDEntry* aEntry, 1.456 + KnownModule* aModule) 1.457 +{ 1.458 + mLock.AssertCurrentThreadOwns(); 1.459 + 1.460 + if (!ProcessSelectorMatches(aEntry->processSelector)) { 1.461 + return; 1.462 + } 1.463 + 1.464 + nsFactoryEntry* f = mFactories.Get(*aEntry->cid); 1.465 + if (f) { 1.466 + NS_WARNING("Re-registering a CID?"); 1.467 + 1.468 + char idstr[NSID_LENGTH]; 1.469 + aEntry->cid->ToProvidedString(idstr); 1.470 + 1.471 + nsCString existing; 1.472 + if (f->mModule) 1.473 + existing = f->mModule->Description(); 1.474 + else 1.475 + existing = "<unknown module>"; 1.476 + SafeMutexAutoUnlock unlock(mLock); 1.477 + LogMessage("While registering XPCOM module %s, trying to re-register CID '%s' already registered by %s.", 1.478 + aModule->Description().get(), 1.479 + idstr, 1.480 + existing.get()); 1.481 + return; 1.482 + } 1.483 + 1.484 + f = new nsFactoryEntry(aEntry, aModule); 1.485 + mFactories.Put(*aEntry->cid, f); 1.486 +} 1.487 + 1.488 +void 1.489 +nsComponentManagerImpl::RegisterContractIDLocked( 1.490 + const mozilla::Module::ContractIDEntry* aEntry) 1.491 +{ 1.492 + mLock.AssertCurrentThreadOwns(); 1.493 + 1.494 + if (!ProcessSelectorMatches(aEntry->processSelector)) { 1.495 + return; 1.496 + } 1.497 + 1.498 + nsFactoryEntry* f = mFactories.Get(*aEntry->cid); 1.499 + if (!f) { 1.500 + NS_ERROR("No CID found when attempting to map contract ID"); 1.501 + 1.502 + char idstr[NSID_LENGTH]; 1.503 + aEntry->cid->ToProvidedString(idstr); 1.504 + 1.505 + LogMessage("Could not map contract ID '%s' to CID %s because no implementation of the CID is registered.", 1.506 + aEntry->contractid, 1.507 + idstr); 1.508 + 1.509 + return; 1.510 + } 1.511 + 1.512 + mContractIDs.Put(nsDependentCString(aEntry->contractid), f); 1.513 +} 1.514 + 1.515 +static void 1.516 +CutExtension(nsCString& path) 1.517 +{ 1.518 + int32_t dotPos = path.RFindChar('.'); 1.519 + if (kNotFound == dotPos) 1.520 + path.Truncate(); 1.521 + else 1.522 + path.Cut(0, dotPos + 1); 1.523 +} 1.524 + 1.525 +void 1.526 +nsComponentManagerImpl::RegisterManifest(NSLocationType aType, 1.527 + FileLocation &aFile, 1.528 + bool aChromeOnly) 1.529 +{ 1.530 + uint32_t len; 1.531 + FileLocation::Data data; 1.532 + nsAutoArrayPtr<char> buf; 1.533 + nsresult rv = aFile.GetData(data); 1.534 + if (NS_SUCCEEDED(rv)) { 1.535 + rv = data.GetSize(&len); 1.536 + } 1.537 + if (NS_SUCCEEDED(rv)) { 1.538 + buf = new char[len + 1]; 1.539 + rv = data.Copy(buf, len); 1.540 + } 1.541 + if (NS_SUCCEEDED(rv)) { 1.542 + buf[len] = '\0'; 1.543 + ParseManifest(aType, aFile, buf, aChromeOnly); 1.544 + } else if (NS_BOOTSTRAPPED_LOCATION != aType) { 1.545 + nsCString uri; 1.546 + aFile.GetURIString(uri); 1.547 + LogMessage("Could not read chrome manifest '%s'.", uri.get()); 1.548 + } 1.549 +} 1.550 + 1.551 +void 1.552 +nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext& cx, int lineno, char *const * argv) 1.553 +{ 1.554 + char* file = argv[0]; 1.555 + FileLocation f(cx.mFile, file); 1.556 + RegisterManifest(cx.mType, f, cx.mChromeOnly); 1.557 +} 1.558 + 1.559 +void 1.560 +nsComponentManagerImpl::ManifestBinaryComponent(ManifestProcessingContext& cx, int lineno, char *const * argv) 1.561 +{ 1.562 + if (cx.mFile.IsZip()) { 1.563 + NS_WARNING("Cannot load binary components from a jar."); 1.564 + LogMessageWithContext(cx.mFile, lineno, 1.565 + "Cannot load binary components from a jar."); 1.566 + return; 1.567 + } 1.568 + 1.569 + FileLocation f(cx.mFile, argv[0]); 1.570 + nsCString uri; 1.571 + f.GetURIString(uri); 1.572 + 1.573 + if (mKnownModules.Get(uri)) { 1.574 + NS_WARNING("Attempting to register a binary component twice."); 1.575 + LogMessageWithContext(cx.mFile, lineno, 1.576 + "Attempting to register a binary component twice."); 1.577 + return; 1.578 + } 1.579 + 1.580 + const mozilla::Module* m = mNativeModuleLoader.LoadModule(f); 1.581 + // The native module loader should report an error here, we don't have to 1.582 + if (!m) 1.583 + return; 1.584 + 1.585 + RegisterModule(m, &f); 1.586 +} 1.587 + 1.588 +void 1.589 +nsComponentManagerImpl::ManifestXPT(ManifestProcessingContext& cx, int lineno, char *const * argv) 1.590 +{ 1.591 + FileLocation f(cx.mFile, argv[0]); 1.592 + uint32_t len; 1.593 + FileLocation::Data data; 1.594 + nsAutoArrayPtr<char> buf; 1.595 + nsresult rv = f.GetData(data); 1.596 + if (NS_SUCCEEDED(rv)) { 1.597 + rv = data.GetSize(&len); 1.598 + } 1.599 + if (NS_SUCCEEDED(rv)) { 1.600 + buf = new char[len]; 1.601 + rv = data.Copy(buf, len); 1.602 + } 1.603 + if (NS_SUCCEEDED(rv)) { 1.604 + XPTInterfaceInfoManager::GetSingleton()->RegisterBuffer(buf, len); 1.605 + } else { 1.606 + nsCString uri; 1.607 + f.GetURIString(uri); 1.608 + LogMessage("Could not read '%s'.", uri.get()); 1.609 + } 1.610 +} 1.611 + 1.612 +void 1.613 +nsComponentManagerImpl::ManifestComponent(ManifestProcessingContext& cx, int lineno, char *const * argv) 1.614 +{ 1.615 + mLock.AssertNotCurrentThreadOwns(); 1.616 + 1.617 + char* id = argv[0]; 1.618 + char* file = argv[1]; 1.619 + 1.620 + nsID cid; 1.621 + if (!cid.Parse(id)) { 1.622 + LogMessageWithContext(cx.mFile, lineno, 1.623 + "Malformed CID: '%s'.", id); 1.624 + return; 1.625 + } 1.626 + 1.627 + // Precompute the hash/file data outside of the lock 1.628 + FileLocation fl(cx.mFile, file); 1.629 + nsCString hash; 1.630 + fl.GetURIString(hash); 1.631 + 1.632 + MutexLock lock(mLock); 1.633 + nsFactoryEntry* f = mFactories.Get(cid); 1.634 + if (f) { 1.635 + char idstr[NSID_LENGTH]; 1.636 + cid.ToProvidedString(idstr); 1.637 + 1.638 + nsCString existing; 1.639 + if (f->mModule) 1.640 + existing = f->mModule->Description(); 1.641 + else 1.642 + existing = "<unknown module>"; 1.643 + 1.644 + lock.Unlock(); 1.645 + 1.646 + LogMessageWithContext(cx.mFile, lineno, 1.647 + "Trying to re-register CID '%s' already registered by %s.", 1.648 + idstr, 1.649 + existing.get()); 1.650 + return; 1.651 + } 1.652 + 1.653 + KnownModule* km; 1.654 + 1.655 + km = mKnownModules.Get(hash); 1.656 + if (!km) { 1.657 + km = new KnownModule(fl); 1.658 + mKnownModules.Put(hash, km); 1.659 + } 1.660 + 1.661 + void* place; 1.662 + 1.663 + PL_ARENA_ALLOCATE(place, &mArena, sizeof(nsCID)); 1.664 + nsID* permanentCID = static_cast<nsID*>(place); 1.665 + *permanentCID = cid; 1.666 + 1.667 + PL_ARENA_ALLOCATE(place, &mArena, sizeof(mozilla::Module::CIDEntry)); 1.668 + mozilla::Module::CIDEntry* e = new (place) mozilla::Module::CIDEntry(); 1.669 + e->cid = permanentCID; 1.670 + 1.671 + f = new nsFactoryEntry(e, km); 1.672 + mFactories.Put(cid, f); 1.673 +} 1.674 + 1.675 +void 1.676 +nsComponentManagerImpl::ManifestContract(ManifestProcessingContext& cx, int lineno, char *const * argv) 1.677 +{ 1.678 + mLock.AssertNotCurrentThreadOwns(); 1.679 + 1.680 + char* contract = argv[0]; 1.681 + char* id = argv[1]; 1.682 + 1.683 + nsID cid; 1.684 + if (!cid.Parse(id)) { 1.685 + LogMessageWithContext(cx.mFile, lineno, 1.686 + "Malformed CID: '%s'.", id); 1.687 + return; 1.688 + } 1.689 + 1.690 + MutexLock lock(mLock); 1.691 + nsFactoryEntry* f = mFactories.Get(cid); 1.692 + if (!f) { 1.693 + lock.Unlock(); 1.694 + LogMessageWithContext(cx.mFile, lineno, 1.695 + "Could not map contract ID '%s' to CID %s because no implementation of the CID is registered.", 1.696 + contract, id); 1.697 + return; 1.698 + } 1.699 + 1.700 + mContractIDs.Put(nsDependentCString(contract), f); 1.701 +} 1.702 + 1.703 +void 1.704 +nsComponentManagerImpl::ManifestCategory(ManifestProcessingContext& cx, int lineno, char *const * argv) 1.705 +{ 1.706 + char* category = argv[0]; 1.707 + char* key = argv[1]; 1.708 + char* value = argv[2]; 1.709 + 1.710 + nsCategoryManager::GetSingleton()-> 1.711 + AddCategoryEntry(category, key, value); 1.712 +} 1.713 + 1.714 +void 1.715 +nsComponentManagerImpl::RereadChromeManifests(bool aChromeOnly) 1.716 +{ 1.717 + for (uint32_t i = 0; i < sModuleLocations->Length(); ++i) { 1.718 + ComponentLocation& l = sModuleLocations->ElementAt(i); 1.719 + RegisterManifest(l.type, l.location, aChromeOnly); 1.720 + } 1.721 +} 1.722 + 1.723 +bool 1.724 +nsComponentManagerImpl::KnownModule::EnsureLoader() 1.725 +{ 1.726 + if (!mLoader) { 1.727 + nsCString extension; 1.728 + mFile.GetURIString(extension); 1.729 + CutExtension(extension); 1.730 + mLoader = nsComponentManagerImpl::gComponentManager->LoaderForExtension(extension); 1.731 + } 1.732 + return !!mLoader; 1.733 +} 1.734 + 1.735 +bool 1.736 +nsComponentManagerImpl::KnownModule::Load() 1.737 +{ 1.738 + if (mFailed) 1.739 + return false; 1.740 + if (!mModule) { 1.741 + if (!EnsureLoader()) 1.742 + return false; 1.743 + 1.744 + mModule = mLoader->LoadModule(mFile); 1.745 + 1.746 + if (!mModule) { 1.747 + mFailed = true; 1.748 + return false; 1.749 + } 1.750 + } 1.751 + if (!mLoaded) { 1.752 + if (mModule->loadProc) { 1.753 + nsresult rv = mModule->loadProc(); 1.754 + if (NS_FAILED(rv)) { 1.755 + mFailed = true; 1.756 + return false; 1.757 + } 1.758 + } 1.759 + mLoaded = true; 1.760 + } 1.761 + return true; 1.762 +} 1.763 + 1.764 +nsCString 1.765 +nsComponentManagerImpl::KnownModule::Description() const 1.766 +{ 1.767 + nsCString s; 1.768 + if (mFile) 1.769 + mFile.GetURIString(s); 1.770 + else 1.771 + s = "<static module>"; 1.772 + return s; 1.773 +} 1.774 + 1.775 +nsresult nsComponentManagerImpl::Shutdown(void) 1.776 +{ 1.777 + PR_ASSERT(NORMAL == mStatus); 1.778 + 1.779 + mStatus = SHUTDOWN_IN_PROGRESS; 1.780 + 1.781 + // Shutdown the component manager 1.782 + PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning Shutdown.")); 1.783 + 1.784 + UnregisterWeakMemoryReporter(this); 1.785 + 1.786 + // Release all cached factories 1.787 + mContractIDs.Clear(); 1.788 + mFactories.Clear(); // XXX release the objects, don't just clear 1.789 + mLoaderMap.Clear(); 1.790 + mKnownModules.Clear(); 1.791 + mKnownStaticModules.Clear(); 1.792 + 1.793 + delete sStaticModules; 1.794 + delete sModuleLocations; 1.795 + 1.796 + // Unload libraries 1.797 + mNativeModuleLoader.UnloadLibraries(); 1.798 + 1.799 + // delete arena for strings and small objects 1.800 + PL_FinishArenaPool(&mArena); 1.801 + 1.802 + mStatus = SHUTDOWN_COMPLETE; 1.803 + 1.804 + PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Shutdown complete.")); 1.805 + 1.806 + return NS_OK; 1.807 +} 1.808 + 1.809 +nsComponentManagerImpl::~nsComponentManagerImpl() 1.810 +{ 1.811 + PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning destruction.")); 1.812 + 1.813 + if (SHUTDOWN_COMPLETE != mStatus) 1.814 + Shutdown(); 1.815 + 1.816 + PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Destroyed.")); 1.817 +} 1.818 + 1.819 +NS_IMPL_ISUPPORTS( 1.820 + nsComponentManagerImpl, 1.821 + nsIComponentManager, 1.822 + nsIServiceManager, 1.823 + nsIComponentRegistrar, 1.824 + nsISupportsWeakReference, 1.825 + nsIInterfaceRequestor, 1.826 + nsIMemoryReporter) 1.827 + 1.828 +nsresult 1.829 +nsComponentManagerImpl::GetInterface(const nsIID & uuid, void **result) 1.830 +{ 1.831 + NS_WARNING("This isn't supported"); 1.832 + // fall through to QI as anything QIable is a superset of what can be 1.833 + // got via the GetInterface() 1.834 + return QueryInterface(uuid, result); 1.835 +} 1.836 + 1.837 +nsFactoryEntry * 1.838 +nsComponentManagerImpl::GetFactoryEntry(const char *aContractID, 1.839 + uint32_t aContractIDLen) 1.840 +{ 1.841 + SafeMutexAutoLock lock(mLock); 1.842 + return mContractIDs.Get(nsDependentCString(aContractID, aContractIDLen)); 1.843 +} 1.844 + 1.845 + 1.846 +nsFactoryEntry * 1.847 +nsComponentManagerImpl::GetFactoryEntry(const nsCID &aClass) 1.848 +{ 1.849 + SafeMutexAutoLock lock(mLock); 1.850 + return mFactories.Get(aClass); 1.851 +} 1.852 + 1.853 +already_AddRefed<nsIFactory> 1.854 +nsComponentManagerImpl::FindFactory(const nsCID& aClass) 1.855 +{ 1.856 + nsFactoryEntry* e = GetFactoryEntry(aClass); 1.857 + if (!e) 1.858 + return nullptr; 1.859 + 1.860 + return e->GetFactory(); 1.861 +} 1.862 + 1.863 +already_AddRefed<nsIFactory> 1.864 +nsComponentManagerImpl::FindFactory(const char *contractID, 1.865 + uint32_t aContractIDLen) 1.866 +{ 1.867 + nsFactoryEntry *entry = GetFactoryEntry(contractID, aContractIDLen); 1.868 + if (!entry) 1.869 + return nullptr; 1.870 + 1.871 + return entry->GetFactory(); 1.872 +} 1.873 + 1.874 +/** 1.875 + * GetClassObject() 1.876 + * 1.877 + * Given a classID, this finds the singleton ClassObject that implements the CID. 1.878 + * Returns an interface of type aIID off the singleton classobject. 1.879 + */ 1.880 +NS_IMETHODIMP 1.881 +nsComponentManagerImpl::GetClassObject(const nsCID &aClass, const nsIID &aIID, 1.882 + void **aResult) 1.883 +{ 1.884 + nsresult rv; 1.885 + 1.886 +#ifdef PR_LOGGING 1.887 + if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_DEBUG)) 1.888 + { 1.889 + char *buf = aClass.ToString(); 1.890 + PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf); 1.891 + if (buf) 1.892 + NS_Free(buf); 1.893 + } 1.894 +#endif 1.895 + 1.896 + PR_ASSERT(aResult != nullptr); 1.897 + 1.898 + nsCOMPtr<nsIFactory> factory = FindFactory(aClass); 1.899 + if (!factory) 1.900 + return NS_ERROR_FACTORY_NOT_REGISTERED; 1.901 + 1.902 + rv = factory->QueryInterface(aIID, aResult); 1.903 + 1.904 + PR_LOG(nsComponentManagerLog, PR_LOG_WARNING, 1.905 + ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED")); 1.906 + 1.907 + return rv; 1.908 +} 1.909 + 1.910 + 1.911 +NS_IMETHODIMP 1.912 +nsComponentManagerImpl::GetClassObjectByContractID(const char *contractID, 1.913 + const nsIID &aIID, 1.914 + void **aResult) 1.915 +{ 1.916 + if (NS_WARN_IF(!aResult) || 1.917 + NS_WARN_IF(!contractID)) 1.918 + return NS_ERROR_INVALID_ARG; 1.919 + 1.920 + nsresult rv; 1.921 + 1.922 + 1.923 +#ifdef PR_LOGGING 1.924 + if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_DEBUG)) 1.925 + { 1.926 + PR_LogPrint("nsComponentManager: GetClassObject(%s)", contractID); 1.927 + } 1.928 +#endif 1.929 + 1.930 + nsCOMPtr<nsIFactory> factory = FindFactory(contractID, strlen(contractID)); 1.931 + if (!factory) 1.932 + return NS_ERROR_FACTORY_NOT_REGISTERED; 1.933 + 1.934 + rv = factory->QueryInterface(aIID, aResult); 1.935 + 1.936 + PR_LOG(nsComponentManagerLog, PR_LOG_WARNING, 1.937 + ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED")); 1.938 + 1.939 + return rv; 1.940 +} 1.941 + 1.942 +/** 1.943 + * CreateInstance() 1.944 + * 1.945 + * Create an instance of an object that implements an interface and belongs 1.946 + * to the implementation aClass using the factory. The factory is immediately 1.947 + * released and not held onto for any longer. 1.948 + */ 1.949 +NS_IMETHODIMP 1.950 +nsComponentManagerImpl::CreateInstance(const nsCID &aClass, 1.951 + nsISupports *aDelegate, 1.952 + const nsIID &aIID, 1.953 + void **aResult) 1.954 +{ 1.955 + // test this first, since there's no point in creating a component during 1.956 + // shutdown -- whether it's available or not would depend on the order it 1.957 + // occurs in the list 1.958 + if (gXPCOMShuttingDown) { 1.959 + // When processing shutdown, don't process new GetService() requests 1.960 +#ifdef SHOW_DENIED_ON_SHUTDOWN 1.961 + nsXPIDLCString cid, iid; 1.962 + cid.Adopt(aClass.ToString()); 1.963 + iid.Adopt(aIID.ToString()); 1.964 + fprintf(stderr, "Creating new instance on shutdown. Denied.\n" 1.965 + " CID: %s\n IID: %s\n", cid.get(), iid.get()); 1.966 +#endif /* SHOW_DENIED_ON_SHUTDOWN */ 1.967 + return NS_ERROR_UNEXPECTED; 1.968 + } 1.969 + 1.970 + if (aResult == nullptr) 1.971 + { 1.972 + return NS_ERROR_NULL_POINTER; 1.973 + } 1.974 + *aResult = nullptr; 1.975 + 1.976 + nsFactoryEntry *entry = GetFactoryEntry(aClass); 1.977 + 1.978 + if (!entry) 1.979 + return NS_ERROR_FACTORY_NOT_REGISTERED; 1.980 + 1.981 +#ifdef SHOW_CI_ON_EXISTING_SERVICE 1.982 + if (entry->mServiceObject) { 1.983 + nsXPIDLCString cid; 1.984 + cid.Adopt(aClass.ToString()); 1.985 + nsAutoCString message; 1.986 + message = NS_LITERAL_CSTRING("You are calling CreateInstance \"") + 1.987 + cid + NS_LITERAL_CSTRING("\" when a service for this CID already exists!"); 1.988 + NS_ERROR(message.get()); 1.989 + } 1.990 +#endif 1.991 + 1.992 + nsresult rv; 1.993 + nsCOMPtr<nsIFactory> factory = entry->GetFactory(); 1.994 + if (factory) 1.995 + { 1.996 + rv = factory->CreateInstance(aDelegate, aIID, aResult); 1.997 + if (NS_SUCCEEDED(rv) && !*aResult) { 1.998 + NS_ERROR("Factory did not return an object but returned success!"); 1.999 + rv = NS_ERROR_SERVICE_NOT_FOUND; 1.1000 + } 1.1001 + } 1.1002 + else { 1.1003 + // Translate error values 1.1004 + rv = NS_ERROR_FACTORY_NOT_REGISTERED; 1.1005 + } 1.1006 + 1.1007 +#ifdef PR_LOGGING 1.1008 + if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING)) 1.1009 + { 1.1010 + char *buf = aClass.ToString(); 1.1011 + PR_LOG(nsComponentManagerLog, PR_LOG_WARNING, 1.1012 + ("nsComponentManager: CreateInstance(%s) %s", buf, 1.1013 + NS_SUCCEEDED(rv) ? "succeeded" : "FAILED")); 1.1014 + if (buf) 1.1015 + NS_Free(buf); 1.1016 + } 1.1017 +#endif 1.1018 + 1.1019 + return rv; 1.1020 +} 1.1021 + 1.1022 +/** 1.1023 + * CreateInstanceByContractID() 1.1024 + * 1.1025 + * A variant of CreateInstance() that creates an instance of the object that 1.1026 + * implements the interface aIID and whose implementation has a contractID aContractID. 1.1027 + * 1.1028 + * This is only a convenience routine that turns around can calls the 1.1029 + * CreateInstance() with classid and iid. 1.1030 + */ 1.1031 +NS_IMETHODIMP 1.1032 +nsComponentManagerImpl::CreateInstanceByContractID(const char *aContractID, 1.1033 + nsISupports *aDelegate, 1.1034 + const nsIID &aIID, 1.1035 + void **aResult) 1.1036 +{ 1.1037 + if (NS_WARN_IF(!aContractID)) 1.1038 + return NS_ERROR_INVALID_ARG; 1.1039 + 1.1040 + // test this first, since there's no point in creating a component during 1.1041 + // shutdown -- whether it's available or not would depend on the order it 1.1042 + // occurs in the list 1.1043 + if (gXPCOMShuttingDown) { 1.1044 + // When processing shutdown, don't process new GetService() requests 1.1045 +#ifdef SHOW_DENIED_ON_SHUTDOWN 1.1046 + nsXPIDLCString iid; 1.1047 + iid.Adopt(aIID.ToString()); 1.1048 + fprintf(stderr, "Creating new instance on shutdown. Denied.\n" 1.1049 + " ContractID: %s\n IID: %s\n", aContractID, iid.get()); 1.1050 +#endif /* SHOW_DENIED_ON_SHUTDOWN */ 1.1051 + return NS_ERROR_UNEXPECTED; 1.1052 + } 1.1053 + 1.1054 + if (aResult == nullptr) 1.1055 + { 1.1056 + return NS_ERROR_NULL_POINTER; 1.1057 + } 1.1058 + *aResult = nullptr; 1.1059 + 1.1060 + nsFactoryEntry *entry = GetFactoryEntry(aContractID, strlen(aContractID)); 1.1061 + 1.1062 + if (!entry) 1.1063 + return NS_ERROR_FACTORY_NOT_REGISTERED; 1.1064 + 1.1065 +#ifdef SHOW_CI_ON_EXISTING_SERVICE 1.1066 + if (entry->mServiceObject) { 1.1067 + nsAutoCString message; 1.1068 + message = 1.1069 + NS_LITERAL_CSTRING("You are calling CreateInstance \"") + 1.1070 + nsDependentCString(aContractID) + 1.1071 + NS_LITERAL_CSTRING("\" when a service for this CID already exists! " 1.1072 + "Add it to abusedContracts to track down the service consumer."); 1.1073 + NS_ERROR(message.get()); 1.1074 + } 1.1075 +#endif 1.1076 + 1.1077 + nsresult rv; 1.1078 + nsCOMPtr<nsIFactory> factory = entry->GetFactory(); 1.1079 + if (factory) 1.1080 + { 1.1081 + 1.1082 + rv = factory->CreateInstance(aDelegate, aIID, aResult); 1.1083 + if (NS_SUCCEEDED(rv) && !*aResult) { 1.1084 + NS_ERROR("Factory did not return an object but returned success!"); 1.1085 + rv = NS_ERROR_SERVICE_NOT_FOUND; 1.1086 + } 1.1087 + } 1.1088 + else { 1.1089 + // Translate error values 1.1090 + rv = NS_ERROR_FACTORY_NOT_REGISTERED; 1.1091 + } 1.1092 + 1.1093 + PR_LOG(nsComponentManagerLog, PR_LOG_WARNING, 1.1094 + ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID, 1.1095 + NS_SUCCEEDED(rv) ? "succeeded" : "FAILED")); 1.1096 + 1.1097 + return rv; 1.1098 +} 1.1099 + 1.1100 +static PLDHashOperator 1.1101 +FreeFactoryEntries(const nsID& aCID, 1.1102 + nsFactoryEntry* aEntry, 1.1103 + void* arg) 1.1104 +{ 1.1105 + aEntry->mFactory = nullptr; 1.1106 + aEntry->mServiceObject = nullptr; 1.1107 + return PL_DHASH_NEXT; 1.1108 +} 1.1109 + 1.1110 +nsresult 1.1111 +nsComponentManagerImpl::FreeServices() 1.1112 +{ 1.1113 + NS_ASSERTION(gXPCOMShuttingDown, "Must be shutting down in order to free all services"); 1.1114 + 1.1115 + if (!gXPCOMShuttingDown) 1.1116 + return NS_ERROR_FAILURE; 1.1117 + 1.1118 + mFactories.EnumerateRead(FreeFactoryEntries, nullptr); 1.1119 + return NS_OK; 1.1120 +} 1.1121 + 1.1122 +// This should only ever be called within the monitor! 1.1123 +nsComponentManagerImpl::PendingServiceInfo* 1.1124 +nsComponentManagerImpl::AddPendingService(const nsCID& aServiceCID, 1.1125 + PRThread* aThread) 1.1126 +{ 1.1127 + PendingServiceInfo* newInfo = mPendingServices.AppendElement(); 1.1128 + if (newInfo) { 1.1129 + newInfo->cid = &aServiceCID; 1.1130 + newInfo->thread = aThread; 1.1131 + } 1.1132 + return newInfo; 1.1133 +} 1.1134 + 1.1135 +// This should only ever be called within the monitor! 1.1136 +void 1.1137 +nsComponentManagerImpl::RemovePendingService(const nsCID& aServiceCID) 1.1138 +{ 1.1139 + uint32_t pendingCount = mPendingServices.Length(); 1.1140 + for (uint32_t index = 0; index < pendingCount; ++index) { 1.1141 + const PendingServiceInfo& info = mPendingServices.ElementAt(index); 1.1142 + if (info.cid->Equals(aServiceCID)) { 1.1143 + mPendingServices.RemoveElementAt(index); 1.1144 + return; 1.1145 + } 1.1146 + } 1.1147 +} 1.1148 + 1.1149 +// This should only ever be called within the monitor! 1.1150 +PRThread* 1.1151 +nsComponentManagerImpl::GetPendingServiceThread(const nsCID& aServiceCID) const 1.1152 +{ 1.1153 + uint32_t pendingCount = mPendingServices.Length(); 1.1154 + for (uint32_t index = 0; index < pendingCount; ++index) { 1.1155 + const PendingServiceInfo& info = mPendingServices.ElementAt(index); 1.1156 + if (info.cid->Equals(aServiceCID)) { 1.1157 + return info.thread; 1.1158 + } 1.1159 + } 1.1160 + return nullptr; 1.1161 +} 1.1162 + 1.1163 +NS_IMETHODIMP 1.1164 +nsComponentManagerImpl::GetService(const nsCID& aClass, 1.1165 + const nsIID& aIID, 1.1166 + void* *result) 1.1167 +{ 1.1168 + // test this first, since there's no point in returning a service during 1.1169 + // shutdown -- whether it's available or not would depend on the order it 1.1170 + // occurs in the list 1.1171 + if (gXPCOMShuttingDown) { 1.1172 + // When processing shutdown, don't process new GetService() requests 1.1173 +#ifdef SHOW_DENIED_ON_SHUTDOWN 1.1174 + nsXPIDLCString cid, iid; 1.1175 + cid.Adopt(aClass.ToString()); 1.1176 + iid.Adopt(aIID.ToString()); 1.1177 + fprintf(stderr, "Getting service on shutdown. Denied.\n" 1.1178 + " CID: %s\n IID: %s\n", cid.get(), iid.get()); 1.1179 +#endif /* SHOW_DENIED_ON_SHUTDOWN */ 1.1180 + return NS_ERROR_UNEXPECTED; 1.1181 + } 1.1182 + 1.1183 + // `service` must be released after the lock is released, so it must be 1.1184 + // declared before the lock in this C++ block. 1.1185 + nsCOMPtr<nsISupports> service; 1.1186 + MutexLock lock(mLock); 1.1187 + 1.1188 + nsFactoryEntry* entry = mFactories.Get(aClass); 1.1189 + if (!entry) 1.1190 + return NS_ERROR_FACTORY_NOT_REGISTERED; 1.1191 + 1.1192 + if (entry->mServiceObject) { 1.1193 + lock.Unlock(); 1.1194 + return entry->mServiceObject->QueryInterface(aIID, result); 1.1195 + } 1.1196 + 1.1197 + PRThread* currentPRThread = PR_GetCurrentThread(); 1.1198 + MOZ_ASSERT(currentPRThread, "This should never be null!"); 1.1199 + 1.1200 + // Needed to optimize the event loop below. 1.1201 + nsIThread* currentThread = nullptr; 1.1202 + 1.1203 + PRThread* pendingPRThread; 1.1204 + while ((pendingPRThread = GetPendingServiceThread(aClass))) { 1.1205 + if (pendingPRThread == currentPRThread) { 1.1206 + NS_ERROR("Recursive GetService!"); 1.1207 + return NS_ERROR_NOT_AVAILABLE; 1.1208 + } 1.1209 + 1.1210 + 1.1211 + SafeMutexAutoUnlock unlockPending(mLock); 1.1212 + 1.1213 + if (!currentThread) { 1.1214 + currentThread = NS_GetCurrentThread(); 1.1215 + MOZ_ASSERT(currentThread, "This should never be null!"); 1.1216 + } 1.1217 + 1.1218 + // This will process a single event or yield the thread if no event is 1.1219 + // pending. 1.1220 + if (!NS_ProcessNextEvent(currentThread, false)) { 1.1221 + PR_Sleep(PR_INTERVAL_NO_WAIT); 1.1222 + } 1.1223 + } 1.1224 + 1.1225 + // It's still possible that the other thread failed to create the 1.1226 + // service so we're not guaranteed to have an entry or service yet. 1.1227 + if (entry->mServiceObject) { 1.1228 + lock.Unlock(); 1.1229 + return entry->mServiceObject->QueryInterface(aIID, result); 1.1230 + } 1.1231 + 1.1232 +#ifdef DEBUG 1.1233 + PendingServiceInfo* newInfo = 1.1234 +#endif 1.1235 + AddPendingService(aClass, currentPRThread); 1.1236 + NS_ASSERTION(newInfo, "Failed to add info to the array!"); 1.1237 + 1.1238 + // We need to not be holding the service manager's lock while calling 1.1239 + // CreateInstance, because it invokes user code which could try to re-enter 1.1240 + // the service manager: 1.1241 + 1.1242 + nsresult rv; 1.1243 + { 1.1244 + SafeMutexAutoUnlock unlock(mLock); 1.1245 + rv = CreateInstance(aClass, nullptr, aIID, getter_AddRefs(service)); 1.1246 + } 1.1247 + if (NS_SUCCEEDED(rv) && !service) { 1.1248 + NS_ERROR("Factory did not return an object but returned success"); 1.1249 + return NS_ERROR_SERVICE_NOT_FOUND; 1.1250 + } 1.1251 + 1.1252 +#ifdef DEBUG 1.1253 + pendingPRThread = GetPendingServiceThread(aClass); 1.1254 + MOZ_ASSERT(pendingPRThread == currentPRThread, 1.1255 + "Pending service array has been changed!"); 1.1256 +#endif 1.1257 + RemovePendingService(aClass); 1.1258 + 1.1259 + if (NS_FAILED(rv)) 1.1260 + return rv; 1.1261 + 1.1262 + NS_ASSERTION(!entry->mServiceObject, "Created two instances of a service!"); 1.1263 + 1.1264 + entry->mServiceObject = service.forget(); 1.1265 + 1.1266 + lock.Unlock(); 1.1267 + nsISupports** sresult = reinterpret_cast<nsISupports**>(result); 1.1268 + *sresult = entry->mServiceObject; 1.1269 + (*sresult)->AddRef(); 1.1270 + 1.1271 + return NS_OK; 1.1272 +} 1.1273 + 1.1274 +NS_IMETHODIMP 1.1275 +nsComponentManagerImpl::IsServiceInstantiated(const nsCID & aClass, 1.1276 + const nsIID& aIID, 1.1277 + bool *result) 1.1278 +{ 1.1279 + // Now we want to get the service if we already got it. If not, we don't want 1.1280 + // to create an instance of it. mmh! 1.1281 + 1.1282 + // test this first, since there's no point in returning a service during 1.1283 + // shutdown -- whether it's available or not would depend on the order it 1.1284 + // occurs in the list 1.1285 + if (gXPCOMShuttingDown) { 1.1286 + // When processing shutdown, don't process new GetService() requests 1.1287 +#ifdef SHOW_DENIED_ON_SHUTDOWN 1.1288 + nsXPIDLCString cid, iid; 1.1289 + cid.Adopt(aClass.ToString()); 1.1290 + iid.Adopt(aIID.ToString()); 1.1291 + fprintf(stderr, "Checking for service on shutdown. Denied.\n" 1.1292 + " CID: %s\n IID: %s\n", cid.get(), iid.get()); 1.1293 +#endif /* SHOW_DENIED_ON_SHUTDOWN */ 1.1294 + return NS_ERROR_UNEXPECTED; 1.1295 + } 1.1296 + 1.1297 + nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE; 1.1298 + nsFactoryEntry* entry; 1.1299 + 1.1300 + { 1.1301 + SafeMutexAutoLock lock(mLock); 1.1302 + entry = mFactories.Get(aClass); 1.1303 + } 1.1304 + 1.1305 + if (entry && entry->mServiceObject) { 1.1306 + nsCOMPtr<nsISupports> service; 1.1307 + rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service)); 1.1308 + *result = (service!=nullptr); 1.1309 + } 1.1310 + 1.1311 + return rv; 1.1312 +} 1.1313 + 1.1314 +NS_IMETHODIMP nsComponentManagerImpl::IsServiceInstantiatedByContractID(const char *aContractID, 1.1315 + const nsIID& aIID, 1.1316 + bool *result) 1.1317 +{ 1.1318 + // Now we want to get the service if we already got it. If not, we don't want 1.1319 + // to create an instance of it. mmh! 1.1320 + 1.1321 + // test this first, since there's no point in returning a service during 1.1322 + // shutdown -- whether it's available or not would depend on the order it 1.1323 + // occurs in the list 1.1324 + if (gXPCOMShuttingDown) { 1.1325 + // When processing shutdown, don't process new GetService() requests 1.1326 +#ifdef SHOW_DENIED_ON_SHUTDOWN 1.1327 + nsXPIDLCString iid; 1.1328 + iid.Adopt(aIID.ToString()); 1.1329 + fprintf(stderr, "Checking for service on shutdown. Denied.\n" 1.1330 + " ContractID: %s\n IID: %s\n", aContractID, iid.get()); 1.1331 +#endif /* SHOW_DENIED_ON_SHUTDOWN */ 1.1332 + return NS_ERROR_UNEXPECTED; 1.1333 + } 1.1334 + 1.1335 + nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE; 1.1336 + nsFactoryEntry *entry; 1.1337 + { 1.1338 + SafeMutexAutoLock lock(mLock); 1.1339 + entry = mContractIDs.Get(nsDependentCString(aContractID)); 1.1340 + } 1.1341 + 1.1342 + if (entry && entry->mServiceObject) { 1.1343 + nsCOMPtr<nsISupports> service; 1.1344 + rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service)); 1.1345 + *result = (service!=nullptr); 1.1346 + } 1.1347 + return rv; 1.1348 +} 1.1349 + 1.1350 + 1.1351 +NS_IMETHODIMP 1.1352 +nsComponentManagerImpl::GetServiceByContractID(const char* aContractID, 1.1353 + const nsIID& aIID, 1.1354 + void* *result) 1.1355 +{ 1.1356 + // test this first, since there's no point in returning a service during 1.1357 + // shutdown -- whether it's available or not would depend on the order it 1.1358 + // occurs in the list 1.1359 + if (gXPCOMShuttingDown) { 1.1360 + // When processing shutdown, don't process new GetService() requests 1.1361 +#ifdef SHOW_DENIED_ON_SHUTDOWN 1.1362 + nsXPIDLCString iid; 1.1363 + iid.Adopt(aIID.ToString()); 1.1364 + fprintf(stderr, "Getting service on shutdown. Denied.\n" 1.1365 + " ContractID: %s\n IID: %s\n", aContractID, iid.get()); 1.1366 +#endif /* SHOW_DENIED_ON_SHUTDOWN */ 1.1367 + return NS_ERROR_UNEXPECTED; 1.1368 + } 1.1369 + 1.1370 + // `service` must be released after the lock is released, so it must be 1.1371 + // declared before the lock in this C++ block. 1.1372 + nsCOMPtr<nsISupports> service; 1.1373 + MutexLock lock(mLock); 1.1374 + 1.1375 + nsFactoryEntry *entry = mContractIDs.Get(nsDependentCString(aContractID)); 1.1376 + if (!entry) 1.1377 + return NS_ERROR_FACTORY_NOT_REGISTERED; 1.1378 + 1.1379 + if (entry->mServiceObject) { 1.1380 + // We need to not be holding the service manager's monitor while calling 1.1381 + // QueryInterface, because it invokes user code which could try to re-enter 1.1382 + // the service manager, or try to grab some other lock/monitor/condvar 1.1383 + // and deadlock, e.g. bug 282743. 1.1384 + // `entry` is valid until XPCOM shutdown, so we can safely use it after 1.1385 + // exiting the lock. 1.1386 + lock.Unlock(); 1.1387 + return entry->mServiceObject->QueryInterface(aIID, result); 1.1388 + } 1.1389 + 1.1390 + PRThread* currentPRThread = PR_GetCurrentThread(); 1.1391 + MOZ_ASSERT(currentPRThread, "This should never be null!"); 1.1392 + 1.1393 + // Needed to optimize the event loop below. 1.1394 + nsIThread* currentThread = nullptr; 1.1395 + 1.1396 + PRThread* pendingPRThread; 1.1397 + while ((pendingPRThread = GetPendingServiceThread(*entry->mCIDEntry->cid))) { 1.1398 + if (pendingPRThread == currentPRThread) { 1.1399 + NS_ERROR("Recursive GetService!"); 1.1400 + return NS_ERROR_NOT_AVAILABLE; 1.1401 + } 1.1402 + 1.1403 + SafeMutexAutoUnlock unlockPending(mLock); 1.1404 + 1.1405 + if (!currentThread) { 1.1406 + currentThread = NS_GetCurrentThread(); 1.1407 + MOZ_ASSERT(currentThread, "This should never be null!"); 1.1408 + } 1.1409 + 1.1410 + // This will process a single event or yield the thread if no event is 1.1411 + // pending. 1.1412 + if (!NS_ProcessNextEvent(currentThread, false)) { 1.1413 + PR_Sleep(PR_INTERVAL_NO_WAIT); 1.1414 + } 1.1415 + } 1.1416 + 1.1417 + if (currentThread && entry->mServiceObject) { 1.1418 + // If we have a currentThread then we must have waited on another thread 1.1419 + // to create the service. Grab it now if that succeeded. 1.1420 + lock.Unlock(); 1.1421 + return entry->mServiceObject->QueryInterface(aIID, result); 1.1422 + } 1.1423 + 1.1424 +#ifdef DEBUG 1.1425 + PendingServiceInfo* newInfo = 1.1426 +#endif 1.1427 + AddPendingService(*entry->mCIDEntry->cid, currentPRThread); 1.1428 + NS_ASSERTION(newInfo, "Failed to add info to the array!"); 1.1429 + 1.1430 + // We need to not be holding the service manager's lock while calling 1.1431 + // CreateInstance, because it invokes user code which could try to re-enter 1.1432 + // the service manager: 1.1433 + 1.1434 + nsresult rv; 1.1435 + { 1.1436 + SafeMutexAutoUnlock unlock(mLock); 1.1437 + rv = CreateInstanceByContractID(aContractID, nullptr, aIID, 1.1438 + getter_AddRefs(service)); 1.1439 + } 1.1440 + if (NS_SUCCEEDED(rv) && !service) { 1.1441 + NS_ERROR("Factory did not return an object but returned success"); 1.1442 + return NS_ERROR_SERVICE_NOT_FOUND; 1.1443 + } 1.1444 + 1.1445 +#ifdef DEBUG 1.1446 + pendingPRThread = GetPendingServiceThread(*entry->mCIDEntry->cid); 1.1447 + MOZ_ASSERT(pendingPRThread == currentPRThread, 1.1448 + "Pending service array has been changed!"); 1.1449 +#endif 1.1450 + RemovePendingService(*entry->mCIDEntry->cid); 1.1451 + 1.1452 + if (NS_FAILED(rv)) 1.1453 + return rv; 1.1454 + 1.1455 + NS_ASSERTION(!entry->mServiceObject, "Created two instances of a service!"); 1.1456 + 1.1457 + entry->mServiceObject = service.forget(); 1.1458 + 1.1459 + lock.Unlock(); 1.1460 + 1.1461 + nsISupports** sresult = reinterpret_cast<nsISupports**>(result); 1.1462 + *sresult = entry->mServiceObject; 1.1463 + (*sresult)->AddRef(); 1.1464 + 1.1465 + return NS_OK; 1.1466 +} 1.1467 + 1.1468 +already_AddRefed<mozilla::ModuleLoader> 1.1469 +nsComponentManagerImpl::LoaderForExtension(const nsACString& aExt) 1.1470 +{ 1.1471 + nsCOMPtr<mozilla::ModuleLoader> loader = mLoaderMap.Get(aExt); 1.1472 + if (!loader) { 1.1473 + loader = do_GetServiceFromCategory("module-loader", 1.1474 + PromiseFlatCString(aExt).get()); 1.1475 + if (!loader) 1.1476 + return nullptr; 1.1477 + 1.1478 + mLoaderMap.Put(aExt, loader); 1.1479 + } 1.1480 + 1.1481 + return loader.forget(); 1.1482 +} 1.1483 + 1.1484 +NS_IMETHODIMP 1.1485 +nsComponentManagerImpl::RegisterFactory(const nsCID& aClass, 1.1486 + const char* aName, 1.1487 + const char* aContractID, 1.1488 + nsIFactory* aFactory) 1.1489 +{ 1.1490 + if (!aFactory) { 1.1491 + // If a null factory is passed in, this call just wants to reset 1.1492 + // the contract ID to point to an existing CID entry. 1.1493 + if (!aContractID) 1.1494 + return NS_ERROR_INVALID_ARG; 1.1495 + 1.1496 + SafeMutexAutoLock lock(mLock); 1.1497 + nsFactoryEntry* oldf = mFactories.Get(aClass); 1.1498 + if (!oldf) 1.1499 + return NS_ERROR_FACTORY_NOT_REGISTERED; 1.1500 + 1.1501 + mContractIDs.Put(nsDependentCString(aContractID), oldf); 1.1502 + return NS_OK; 1.1503 + } 1.1504 + 1.1505 + nsAutoPtr<nsFactoryEntry> f(new nsFactoryEntry(aClass, aFactory)); 1.1506 + 1.1507 + SafeMutexAutoLock lock(mLock); 1.1508 + nsFactoryEntry* oldf = mFactories.Get(aClass); 1.1509 + if (oldf) 1.1510 + return NS_ERROR_FACTORY_EXISTS; 1.1511 + 1.1512 + if (aContractID) 1.1513 + mContractIDs.Put(nsDependentCString(aContractID), f); 1.1514 + 1.1515 + mFactories.Put(aClass, f.forget()); 1.1516 + 1.1517 + return NS_OK; 1.1518 +} 1.1519 + 1.1520 +NS_IMETHODIMP 1.1521 +nsComponentManagerImpl::UnregisterFactory(const nsCID& aClass, 1.1522 + nsIFactory* aFactory) 1.1523 +{ 1.1524 + // Don't release the dying factory or service object until releasing 1.1525 + // the component manager monitor. 1.1526 + nsCOMPtr<nsIFactory> dyingFactory; 1.1527 + nsCOMPtr<nsISupports> dyingServiceObject; 1.1528 + 1.1529 + { 1.1530 + SafeMutexAutoLock lock(mLock); 1.1531 + nsFactoryEntry* f = mFactories.Get(aClass); 1.1532 + if (!f || f->mFactory != aFactory) 1.1533 + return NS_ERROR_FACTORY_NOT_REGISTERED; 1.1534 + 1.1535 + mFactories.Remove(aClass); 1.1536 + 1.1537 + // This might leave a stale contractid -> factory mapping in 1.1538 + // place, so null out the factory entry (see 1.1539 + // nsFactoryEntry::GetFactory) 1.1540 + f->mFactory.swap(dyingFactory); 1.1541 + f->mServiceObject.swap(dyingServiceObject); 1.1542 + } 1.1543 + 1.1544 + return NS_OK; 1.1545 +} 1.1546 + 1.1547 +NS_IMETHODIMP 1.1548 +nsComponentManagerImpl::AutoRegister(nsIFile* aLocation) 1.1549 +{ 1.1550 + XRE_AddManifestLocation(NS_COMPONENT_LOCATION, aLocation); 1.1551 + return NS_OK; 1.1552 +} 1.1553 + 1.1554 +NS_IMETHODIMP 1.1555 +nsComponentManagerImpl::AutoUnregister(nsIFile* aLocation) 1.1556 +{ 1.1557 + NS_ERROR("AutoUnregister not implemented."); 1.1558 + return NS_ERROR_NOT_IMPLEMENTED; 1.1559 +} 1.1560 + 1.1561 +NS_IMETHODIMP 1.1562 +nsComponentManagerImpl::RegisterFactoryLocation(const nsCID& aCID, 1.1563 + const char* aClassName, 1.1564 + const char* aContractID, 1.1565 + nsIFile* aFile, 1.1566 + const char* aLoaderStr, 1.1567 + const char* aType) 1.1568 +{ 1.1569 + NS_ERROR("RegisterFactoryLocation not implemented."); 1.1570 + return NS_ERROR_NOT_IMPLEMENTED; 1.1571 +} 1.1572 + 1.1573 +NS_IMETHODIMP 1.1574 +nsComponentManagerImpl::UnregisterFactoryLocation(const nsCID& aCID, 1.1575 + nsIFile* aFile) 1.1576 +{ 1.1577 + NS_ERROR("UnregisterFactoryLocation not implemented."); 1.1578 + return NS_ERROR_NOT_IMPLEMENTED; 1.1579 +} 1.1580 + 1.1581 +NS_IMETHODIMP 1.1582 +nsComponentManagerImpl::IsCIDRegistered(const nsCID & aClass, 1.1583 + bool *_retval) 1.1584 +{ 1.1585 + *_retval = (nullptr != GetFactoryEntry(aClass)); 1.1586 + return NS_OK; 1.1587 +} 1.1588 + 1.1589 +NS_IMETHODIMP 1.1590 +nsComponentManagerImpl::IsContractIDRegistered(const char *aClass, 1.1591 + bool *_retval) 1.1592 +{ 1.1593 + if (NS_WARN_IF(!aClass)) 1.1594 + return NS_ERROR_INVALID_ARG; 1.1595 + 1.1596 + nsFactoryEntry *entry = GetFactoryEntry(aClass, strlen(aClass)); 1.1597 + 1.1598 + if (entry) 1.1599 + *_retval = true; 1.1600 + else 1.1601 + *_retval = false; 1.1602 + return NS_OK; 1.1603 +} 1.1604 + 1.1605 +static PLDHashOperator 1.1606 +EnumerateCIDHelper(const nsID& id, nsFactoryEntry* entry, void* closure) 1.1607 +{ 1.1608 + nsCOMArray<nsISupports> *array = static_cast<nsCOMArray<nsISupports>*>(closure); 1.1609 + nsCOMPtr<nsISupportsID> wrapper = new nsSupportsIDImpl(); 1.1610 + wrapper->SetData(&id); 1.1611 + array->AppendObject(wrapper); 1.1612 + return PL_DHASH_NEXT; 1.1613 +} 1.1614 + 1.1615 +NS_IMETHODIMP 1.1616 +nsComponentManagerImpl::EnumerateCIDs(nsISimpleEnumerator **aEnumerator) 1.1617 +{ 1.1618 + nsCOMArray<nsISupports> array; 1.1619 + mFactories.EnumerateRead(EnumerateCIDHelper, &array); 1.1620 + 1.1621 + return NS_NewArrayEnumerator(aEnumerator, array); 1.1622 +} 1.1623 + 1.1624 +static PLDHashOperator 1.1625 +EnumerateContractsHelper(const nsACString& contract, nsFactoryEntry* entry, void* closure) 1.1626 +{ 1.1627 + nsTArray<nsCString>* array = static_cast<nsTArray<nsCString>*>(closure); 1.1628 + array->AppendElement(contract); 1.1629 + return PL_DHASH_NEXT; 1.1630 +} 1.1631 + 1.1632 +NS_IMETHODIMP 1.1633 +nsComponentManagerImpl::EnumerateContractIDs(nsISimpleEnumerator **aEnumerator) 1.1634 +{ 1.1635 + nsTArray<nsCString>* array = new nsTArray<nsCString>; 1.1636 + mContractIDs.EnumerateRead(EnumerateContractsHelper, array); 1.1637 + 1.1638 + nsCOMPtr<nsIUTF8StringEnumerator> e; 1.1639 + nsresult rv = NS_NewAdoptingUTF8StringEnumerator(getter_AddRefs(e), array); 1.1640 + if (NS_FAILED(rv)) 1.1641 + return rv; 1.1642 + 1.1643 + return CallQueryInterface(e, aEnumerator); 1.1644 +} 1.1645 + 1.1646 +NS_IMETHODIMP 1.1647 +nsComponentManagerImpl::CIDToContractID(const nsCID & aClass, 1.1648 + char **_retval) 1.1649 +{ 1.1650 + NS_ERROR("CIDTOContractID not implemented"); 1.1651 + return NS_ERROR_FACTORY_NOT_REGISTERED; 1.1652 +} 1.1653 + 1.1654 +NS_IMETHODIMP 1.1655 +nsComponentManagerImpl::ContractIDToCID(const char *aContractID, 1.1656 + nsCID * *_retval) 1.1657 +{ 1.1658 + { 1.1659 + SafeMutexAutoLock lock(mLock); 1.1660 + nsFactoryEntry* entry = mContractIDs.Get(nsDependentCString(aContractID)); 1.1661 + if (entry) { 1.1662 + *_retval = (nsCID*) NS_Alloc(sizeof(nsCID)); 1.1663 + **_retval = *entry->mCIDEntry->cid; 1.1664 + return NS_OK; 1.1665 + } 1.1666 + } 1.1667 + *_retval = nullptr; 1.1668 + return NS_ERROR_FACTORY_NOT_REGISTERED; 1.1669 +} 1.1670 + 1.1671 +static size_t 1.1672 +SizeOfFactoriesEntryExcludingThis(nsIDHashKey::KeyType aKey, 1.1673 + nsFactoryEntry* const &aData, 1.1674 + MallocSizeOf aMallocSizeOf, 1.1675 + void* aUserArg) 1.1676 +{ 1.1677 + return aData->SizeOfIncludingThis(aMallocSizeOf); 1.1678 +} 1.1679 + 1.1680 +static size_t 1.1681 +SizeOfContractIDsEntryExcludingThis(nsCStringHashKey::KeyType aKey, 1.1682 + nsFactoryEntry* const &aData, 1.1683 + MallocSizeOf aMallocSizeOf, 1.1684 + void* aUserArg) 1.1685 +{ 1.1686 + // We don't measure the nsFactoryEntry data because its owned by mFactories 1.1687 + // (which measures them in SizeOfFactoriesEntryExcludingThis). 1.1688 + return aKey.SizeOfExcludingThisMustBeUnshared(aMallocSizeOf); 1.1689 +} 1.1690 + 1.1691 +MOZ_DEFINE_MALLOC_SIZE_OF(ComponentManagerMallocSizeOf) 1.1692 + 1.1693 +NS_IMETHODIMP 1.1694 +nsComponentManagerImpl::CollectReports(nsIHandleReportCallback* aHandleReport, 1.1695 + nsISupports* aData) 1.1696 +{ 1.1697 + return MOZ_COLLECT_REPORT( 1.1698 + "explicit/xpcom/component-manager", KIND_HEAP, UNITS_BYTES, 1.1699 + SizeOfIncludingThis(ComponentManagerMallocSizeOf), 1.1700 + "Memory used for the XPCOM component manager."); 1.1701 +} 1.1702 + 1.1703 +size_t 1.1704 +nsComponentManagerImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) 1.1705 +{ 1.1706 + size_t n = aMallocSizeOf(this); 1.1707 + n += mLoaderMap.SizeOfExcludingThis(nullptr, aMallocSizeOf); 1.1708 + n += mFactories.SizeOfExcludingThis(SizeOfFactoriesEntryExcludingThis, aMallocSizeOf); 1.1709 + n += mContractIDs.SizeOfExcludingThis(SizeOfContractIDsEntryExcludingThis, aMallocSizeOf); 1.1710 + 1.1711 + n += sStaticModules->SizeOfIncludingThis(aMallocSizeOf); 1.1712 + n += sModuleLocations->SizeOfIncludingThis(aMallocSizeOf); 1.1713 + 1.1714 + n += mKnownStaticModules.SizeOfExcludingThis(aMallocSizeOf); 1.1715 + n += mKnownModules.SizeOfExcludingThis(nullptr, aMallocSizeOf); 1.1716 + 1.1717 + n += PL_SizeOfArenaPoolExcludingPool(&mArena, aMallocSizeOf); 1.1718 + 1.1719 + n += mPendingServices.SizeOfExcludingThis(aMallocSizeOf); 1.1720 + 1.1721 + // Measurement of the following members may be added later if DMD finds it is 1.1722 + // worthwhile: 1.1723 + // - mLoaderMap's keys and values 1.1724 + // - mMon 1.1725 + // - sStaticModules' entries 1.1726 + // - sModuleLocations' entries 1.1727 + // - mNativeModuleLoader 1.1728 + // - mKnownStaticModules' entries? 1.1729 + // - mKnownModules' keys and values? 1.1730 + 1.1731 + return n; 1.1732 +} 1.1733 + 1.1734 +//////////////////////////////////////////////////////////////////////////////// 1.1735 +// nsFactoryEntry 1.1736 +//////////////////////////////////////////////////////////////////////////////// 1.1737 + 1.1738 +nsFactoryEntry::nsFactoryEntry(const mozilla::Module::CIDEntry* entry, 1.1739 + nsComponentManagerImpl::KnownModule* module) 1.1740 + : mCIDEntry(entry) 1.1741 + , mModule(module) 1.1742 +{ 1.1743 +} 1.1744 + 1.1745 +nsFactoryEntry::nsFactoryEntry(const nsCID& aCID, nsIFactory* factory) 1.1746 + : mCIDEntry(nullptr) 1.1747 + , mModule(nullptr) 1.1748 + , mFactory(factory) 1.1749 +{ 1.1750 + mozilla::Module::CIDEntry* e = new mozilla::Module::CIDEntry(); 1.1751 + nsCID* cid = new nsCID; 1.1752 + *cid = aCID; 1.1753 + e->cid = cid; 1.1754 + mCIDEntry = e; 1.1755 +} 1.1756 + 1.1757 +nsFactoryEntry::~nsFactoryEntry() 1.1758 +{ 1.1759 + // If this was a RegisterFactory entry, we own the CIDEntry/CID 1.1760 + if (!mModule) { 1.1761 + delete mCIDEntry->cid; 1.1762 + delete mCIDEntry; 1.1763 + } 1.1764 +} 1.1765 + 1.1766 +already_AddRefed<nsIFactory> 1.1767 +nsFactoryEntry::GetFactory() 1.1768 +{ 1.1769 + nsComponentManagerImpl::gComponentManager->mLock.AssertNotCurrentThreadOwns(); 1.1770 + 1.1771 + if (!mFactory) { 1.1772 + // RegisterFactory then UnregisterFactory can leave an entry in mContractIDs 1.1773 + // pointing to an unusable nsFactoryEntry. 1.1774 + if (!mModule) 1.1775 + return nullptr; 1.1776 + 1.1777 + if (!mModule->Load()) 1.1778 + return nullptr; 1.1779 + 1.1780 + // Don't set mFactory directly, it needs to be locked 1.1781 + nsCOMPtr<nsIFactory> factory; 1.1782 + 1.1783 + if (mModule->Module()->getFactoryProc) { 1.1784 + factory = mModule->Module()->getFactoryProc(*mModule->Module(), 1.1785 + *mCIDEntry); 1.1786 + } 1.1787 + else if (mCIDEntry->getFactoryProc) { 1.1788 + factory = mCIDEntry->getFactoryProc(*mModule->Module(), *mCIDEntry); 1.1789 + } 1.1790 + else { 1.1791 + NS_ASSERTION(mCIDEntry->constructorProc, "no getfactory or constructor"); 1.1792 + factory = new mozilla::GenericFactory(mCIDEntry->constructorProc); 1.1793 + } 1.1794 + if (!factory) 1.1795 + return nullptr; 1.1796 + 1.1797 + SafeMutexAutoLock lock(nsComponentManagerImpl::gComponentManager->mLock); 1.1798 + // Threads can race to set mFactory 1.1799 + if (!mFactory) { 1.1800 + factory.swap(mFactory); 1.1801 + } 1.1802 + } 1.1803 + nsCOMPtr<nsIFactory> factory = mFactory; 1.1804 + return factory.forget(); 1.1805 +} 1.1806 + 1.1807 +size_t 1.1808 +nsFactoryEntry::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) 1.1809 +{ 1.1810 + size_t n = aMallocSizeOf(this); 1.1811 + 1.1812 + // Measurement of the following members may be added later if DMD finds it is 1.1813 + // worthwhile: 1.1814 + // - mCIDEntry; 1.1815 + // - mModule; 1.1816 + // - mFactory; 1.1817 + // - mServiceObject; 1.1818 + 1.1819 + return n; 1.1820 +} 1.1821 + 1.1822 +//////////////////////////////////////////////////////////////////////////////// 1.1823 +// Static Access Functions 1.1824 +//////////////////////////////////////////////////////////////////////////////// 1.1825 + 1.1826 +nsresult 1.1827 +NS_GetComponentManager(nsIComponentManager* *result) 1.1828 +{ 1.1829 + if (!nsComponentManagerImpl::gComponentManager) 1.1830 + return NS_ERROR_NOT_INITIALIZED; 1.1831 + 1.1832 + NS_ADDREF(*result = nsComponentManagerImpl::gComponentManager); 1.1833 + return NS_OK; 1.1834 +} 1.1835 + 1.1836 +nsresult 1.1837 +NS_GetServiceManager(nsIServiceManager* *result) 1.1838 +{ 1.1839 + if (!nsComponentManagerImpl::gComponentManager) 1.1840 + return NS_ERROR_NOT_INITIALIZED; 1.1841 + 1.1842 + NS_ADDREF(*result = nsComponentManagerImpl::gComponentManager); 1.1843 + return NS_OK; 1.1844 +} 1.1845 + 1.1846 + 1.1847 +nsresult 1.1848 +NS_GetComponentRegistrar(nsIComponentRegistrar* *result) 1.1849 +{ 1.1850 + if (!nsComponentManagerImpl::gComponentManager) 1.1851 + return NS_ERROR_NOT_INITIALIZED; 1.1852 + 1.1853 + NS_ADDREF(*result = nsComponentManagerImpl::gComponentManager); 1.1854 + return NS_OK; 1.1855 +} 1.1856 + 1.1857 +EXPORT_XPCOM_API(nsresult) 1.1858 +XRE_AddStaticComponent(const mozilla::Module* aComponent) 1.1859 +{ 1.1860 + nsComponentManagerImpl::InitializeStaticModules(); 1.1861 + nsComponentManagerImpl::sStaticModules->AppendElement(aComponent); 1.1862 + 1.1863 + if (nsComponentManagerImpl::gComponentManager && 1.1864 + nsComponentManagerImpl::NORMAL == nsComponentManagerImpl::gComponentManager->mStatus) 1.1865 + nsComponentManagerImpl::gComponentManager->RegisterModule(aComponent, nullptr); 1.1866 + 1.1867 + return NS_OK; 1.1868 +} 1.1869 + 1.1870 +NS_IMETHODIMP 1.1871 +nsComponentManagerImpl::AddBootstrappedManifestLocation(nsIFile* aLocation) 1.1872 +{ 1.1873 + nsString path; 1.1874 + nsresult rv = aLocation->GetPath(path); 1.1875 + if (NS_FAILED(rv)) 1.1876 + return rv; 1.1877 + 1.1878 + if (Substring(path, path.Length() - 4).Equals(NS_LITERAL_STRING(".xpi"))) { 1.1879 + return XRE_AddJarManifestLocation(NS_BOOTSTRAPPED_LOCATION, aLocation); 1.1880 + } 1.1881 + 1.1882 + nsCOMPtr<nsIFile> manifest = 1.1883 + CloneAndAppend(aLocation, NS_LITERAL_CSTRING("chrome.manifest")); 1.1884 + return XRE_AddManifestLocation(NS_BOOTSTRAPPED_LOCATION, manifest); 1.1885 +} 1.1886 + 1.1887 +NS_IMETHODIMP 1.1888 +nsComponentManagerImpl::RemoveBootstrappedManifestLocation(nsIFile* aLocation) 1.1889 +{ 1.1890 + nsCOMPtr<nsIChromeRegistry> cr = mozilla::services::GetChromeRegistryService(); 1.1891 + if (!cr) 1.1892 + return NS_ERROR_FAILURE; 1.1893 + 1.1894 + nsCOMPtr<nsIFile> manifest; 1.1895 + nsString path; 1.1896 + nsresult rv = aLocation->GetPath(path); 1.1897 + if (NS_FAILED(rv)) 1.1898 + return rv; 1.1899 + 1.1900 + nsComponentManagerImpl::ComponentLocation elem; 1.1901 + elem.type = NS_BOOTSTRAPPED_LOCATION; 1.1902 + 1.1903 + if (Substring(path, path.Length() - 4).Equals(NS_LITERAL_STRING(".xpi"))) { 1.1904 + elem.location.Init(aLocation, "chrome.manifest"); 1.1905 + } else { 1.1906 + nsCOMPtr<nsIFile> lf = CloneAndAppend(aLocation, NS_LITERAL_CSTRING("chrome.manifest")); 1.1907 + elem.location.Init(lf); 1.1908 + } 1.1909 + 1.1910 + // Remove reference. 1.1911 + nsComponentManagerImpl::sModuleLocations->RemoveElement(elem, ComponentLocationComparator()); 1.1912 + 1.1913 + rv = cr->CheckForNewChrome(); 1.1914 + return rv; 1.1915 +} 1.1916 + 1.1917 +NS_IMETHODIMP 1.1918 +nsComponentManagerImpl::GetManifestLocations(nsIArray **aLocations) 1.1919 +{ 1.1920 + NS_ENSURE_ARG_POINTER(aLocations); 1.1921 + *aLocations = nullptr; 1.1922 + 1.1923 + if (!sModuleLocations) 1.1924 + return NS_ERROR_NOT_INITIALIZED; 1.1925 + 1.1926 + nsCOMPtr<nsIMutableArray> locations = nsArray::Create(); 1.1927 + nsresult rv; 1.1928 + for (uint32_t i = 0; i < sModuleLocations->Length(); ++i) { 1.1929 + ComponentLocation& l = sModuleLocations->ElementAt(i); 1.1930 + FileLocation loc = l.location; 1.1931 + nsCString uriString; 1.1932 + loc.GetURIString(uriString); 1.1933 + nsCOMPtr<nsIURI> uri; 1.1934 + rv = NS_NewURI(getter_AddRefs(uri), uriString); 1.1935 + if (NS_SUCCEEDED(rv)) 1.1936 + locations->AppendElement(uri, false); 1.1937 + } 1.1938 + 1.1939 + locations.forget(aLocations); 1.1940 + return NS_OK; 1.1941 +} 1.1942 + 1.1943 +EXPORT_XPCOM_API(nsresult) 1.1944 +XRE_AddManifestLocation(NSLocationType aType, nsIFile* aLocation) 1.1945 +{ 1.1946 + nsComponentManagerImpl::InitializeModuleLocations(); 1.1947 + nsComponentManagerImpl::ComponentLocation* c = 1.1948 + nsComponentManagerImpl::sModuleLocations->AppendElement(); 1.1949 + c->type = aType; 1.1950 + c->location.Init(aLocation); 1.1951 + 1.1952 + if (nsComponentManagerImpl::gComponentManager && 1.1953 + nsComponentManagerImpl::NORMAL == nsComponentManagerImpl::gComponentManager->mStatus) 1.1954 + nsComponentManagerImpl::gComponentManager->RegisterManifest(aType, c->location, false); 1.1955 + 1.1956 + return NS_OK; 1.1957 +} 1.1958 + 1.1959 +EXPORT_XPCOM_API(nsresult) 1.1960 +XRE_AddJarManifestLocation(NSLocationType aType, nsIFile* aLocation) 1.1961 +{ 1.1962 + nsComponentManagerImpl::InitializeModuleLocations(); 1.1963 + nsComponentManagerImpl::ComponentLocation* c = 1.1964 + nsComponentManagerImpl::sModuleLocations->AppendElement(); 1.1965 + 1.1966 + c->type = aType; 1.1967 + c->location.Init(aLocation, "chrome.manifest"); 1.1968 + 1.1969 + if (nsComponentManagerImpl::gComponentManager && 1.1970 + nsComponentManagerImpl::NORMAL == nsComponentManagerImpl::gComponentManager->mStatus) 1.1971 + nsComponentManagerImpl::gComponentManager->RegisterManifest(aType, c->location, false); 1.1972 + 1.1973 + return NS_OK; 1.1974 +} 1.1975 +