1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK *****
37 : *
38 : * This Original Code has been modified by IBM Corporation.
39 : * Modifications made by IBM described herein are
40 : * Copyright (c) International Business Machines
41 : * Corporation, 2000
42 : *
43 : * Modifications to Mozilla code or documentation
44 : * identified per MPL Section 3.3
45 : *
46 : * Date Modified by Description of modification
47 : * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
48 : */
49 :
50 : #include <stdlib.h>
51 : #include "nscore.h"
52 : #include "nsISupports.h"
53 : #include "nspr.h"
54 : #include "nsCRT.h" // for atoll
55 :
56 : // Arena used by component manager for storing contractid string, dll
57 : // location strings and small objects
58 : // CAUTION: Arena align mask needs to be defined before including plarena.h
59 : // currently from nsComponentManager.h
60 : #define PL_ARENA_CONST_ALIGN_MASK 7
61 : #define NS_CM_BLOCK_SIZE (1024 * 8)
62 :
63 : #include "nsCategoryManager.h"
64 : #include "nsCOMPtr.h"
65 : #include "nsComponentManager.h"
66 : #include "nsDirectoryService.h"
67 : #include "nsDirectoryServiceDefs.h"
68 : #include "nsCategoryManager.h"
69 : #include "nsCategoryManagerUtils.h"
70 : #include "nsIEnumerator.h"
71 : #include "xptiprivate.h"
72 : #include "nsIConsoleService.h"
73 : #include "nsIObserverService.h"
74 : #include "nsISimpleEnumerator.h"
75 : #include "nsIStringEnumerator.h"
76 : #include "nsXPCOM.h"
77 : #include "nsXPCOMPrivate.h"
78 : #include "nsISupportsPrimitives.h"
79 : #include "nsIClassInfo.h"
80 : #include "nsLocalFile.h"
81 : #include "nsReadableUtils.h"
82 : #include "nsStaticComponents.h"
83 : #include "nsString.h"
84 : #include "nsXPIDLString.h"
85 : #include "prcmon.h"
86 : #include "xptinfo.h" // this after nsISupports, to pick up IID so that xpt stuff doesn't try to define it itself...
87 : #include "nsThreadUtils.h"
88 : #include "prthread.h"
89 : #include "private/pprthred.h"
90 : #include "nsTArray.h"
91 : #include "prio.h"
92 : #include "mozilla/FunctionTimer.h"
93 : #include "ManifestParser.h"
94 : #include "mozilla/Services.h"
95 :
96 : #include "nsManifestLineReader.h"
97 : #include "mozilla/GenericFactory.h"
98 : #include "nsSupportsPrimitives.h"
99 : #include "nsArrayEnumerator.h"
100 : #include "nsStringEnumerator.h"
101 : #include "mozilla/FileUtils.h"
102 :
103 : #include NEW_H // for placement new
104 :
105 : #include "mozilla/Omnijar.h"
106 :
107 : #include "prlog.h"
108 :
109 : using namespace mozilla;
110 :
111 : PRLogModuleInfo* nsComponentManagerLog = nsnull;
112 :
113 : #if 0 || defined (DEBUG_timeless)
114 : #define SHOW_DENIED_ON_SHUTDOWN
115 : #define SHOW_CI_ON_EXISTING_SERVICE
116 : #endif
117 :
118 : // Bloated registry buffer size to improve startup performance -- needs to
119 : // be big enough to fit the entire file into memory or it'll thrash.
120 : // 512K is big enough to allow for some future growth in the registry.
121 : #define BIG_REGISTRY_BUFLEN (512*1024)
122 :
123 : // Common Key Names
124 : const char classIDKeyName[]="classID";
125 : const char classesKeyName[]="contractID";
126 : const char componentsKeyName[]="components";
127 : const char xpcomComponentsKeyName[]="software/mozilla/XPCOM/components";
128 : const char xpcomKeyName[]="software/mozilla/XPCOM";
129 :
130 : // Common Value Names
131 : const char classIDValueName[]="ClassID";
132 : const char classNameValueName[]="ClassName";
133 : const char componentCountValueName[]="ComponentsCount";
134 : const char componentTypeValueName[]="ComponentType";
135 : const char contractIDValueName[]="ContractID";
136 : const char fileSizeValueName[]="FileSize";
137 : const char inprocServerValueName[]="InprocServer";
138 : const char lastModValueName[]="LastModTimeStamp";
139 : const char nativeComponentType[]="application/x-mozilla-native";
140 : const char staticComponentType[]="application/x-mozilla-static";
141 : const char jarComponentType[]="application/x-mozilla-jarjs";
142 : const char versionValueName[]="VersionString";
143 :
144 : const static char XPCOM_ABSCOMPONENT_PREFIX[] = "abs:";
145 : const static char XPCOM_RELCOMPONENT_PREFIX[] = "rel:";
146 : const static char XPCOM_GRECOMPONENT_PREFIX[] = "gre:";
147 :
148 : static const char gIDFormat[] =
149 : "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}";
150 :
151 :
152 : #define NS_EMPTY_IID \
153 : { \
154 : 0x00000000, \
155 : 0x0000, \
156 : 0x0000, \
157 : {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} \
158 : }
159 :
160 : NS_DEFINE_CID(kEmptyCID, NS_EMPTY_IID);
161 : NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
162 :
163 : #define UID_STRING_LENGTH 39
164 :
165 : #ifdef NS_FUNCTION_TIMER
166 : #define COMPMGR_TIME_FUNCTION_CID(cid) \
167 : char cid_buf__[NSID_LENGTH] = { '\0' }; \
168 : cid.ToProvidedString(cid_buf__); \
169 : NS_TIME_FUNCTION_MIN_FMT(5, "%s (line %d) (cid: %s)", MOZ_FUNCTION_NAME, \
170 : __LINE__, cid_buf__)
171 : #define COMPMGR_TIME_FUNCTION_CONTRACTID(cid) \
172 : NS_TIME_FUNCTION_MIN_FMT(5, "%s (line %d) (contractid: %s)", MOZ_FUNCTION_NAME, \
173 : __LINE__, (cid))
174 : #else
175 : #define COMPMGR_TIME_FUNCTION_CID(cid) do {} while (0)
176 : #define COMPMGR_TIME_FUNCTION_CONTRACTID(cid) do {} while (0)
177 : #endif
178 :
179 : nsresult
180 759 : nsGetServiceFromCategory::operator()(const nsIID& aIID, void** aInstancePtr) const
181 : {
182 : nsresult rv;
183 1518 : nsXPIDLCString value;
184 1518 : nsCOMPtr<nsICategoryManager> catman;
185 759 : nsComponentManagerImpl *compMgr = nsComponentManagerImpl::gComponentManager;
186 759 : if (!compMgr) {
187 0 : rv = NS_ERROR_NOT_INITIALIZED;
188 0 : goto error;
189 : }
190 :
191 759 : if (!mCategory || !mEntry) {
192 : // when categories have defaults, use that for null mEntry
193 0 : rv = NS_ERROR_NULL_POINTER;
194 0 : goto error;
195 : }
196 :
197 : rv = compMgr->nsComponentManagerImpl::GetService(kCategoryManagerCID,
198 : NS_GET_IID(nsICategoryManager),
199 759 : getter_AddRefs(catman));
200 759 : if (NS_FAILED(rv)) goto error;
201 :
202 : /* find the contractID for category.entry */
203 759 : rv = catman->GetCategoryEntry(mCategory, mEntry,
204 759 : getter_Copies(value));
205 759 : if (NS_FAILED(rv)) goto error;
206 759 : if (!value) {
207 0 : rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
208 0 : goto error;
209 : }
210 :
211 : rv = compMgr->
212 : nsComponentManagerImpl::GetServiceByContractID(value,
213 759 : aIID, aInstancePtr);
214 759 : if (NS_FAILED(rv)) {
215 : error:
216 0 : *aInstancePtr = 0;
217 : }
218 759 : if (mErrorPtr)
219 0 : *mErrorPtr = rv;
220 759 : return rv;
221 : }
222 :
223 : ////////////////////////////////////////////////////////////////////////////////
224 : // Arena helper functions
225 : ////////////////////////////////////////////////////////////////////////////////
226 : char *
227 885860 : ArenaStrndup(const char *s, PRUint32 len, PLArenaPool *arena)
228 : {
229 : void *mem;
230 : // Include trailing null in the len
231 885860 : PL_ARENA_ALLOCATE(mem, arena, len+1);
232 885860 : if (mem)
233 885860 : memcpy(mem, s, len+1);
234 885860 : return static_cast<char *>(mem);
235 : }
236 :
237 : char*
238 885860 : ArenaStrdup(const char *s, PLArenaPool *arena)
239 : {
240 885860 : return ArenaStrndup(s, strlen(s), arena);
241 : }
242 :
243 : // this is safe to call during InitXPCOM
244 : static already_AddRefed<nsILocalFile>
245 2838 : GetLocationFromDirectoryService(const char* prop)
246 : {
247 5676 : nsCOMPtr<nsIProperties> directoryService;
248 : nsDirectoryService::Create(nsnull,
249 : NS_GET_IID(nsIProperties),
250 2838 : getter_AddRefs(directoryService));
251 :
252 2838 : if (!directoryService)
253 0 : return NULL;
254 :
255 5676 : nsCOMPtr<nsILocalFile> file;
256 2838 : nsresult rv = directoryService->Get(prop,
257 : NS_GET_IID(nsILocalFile),
258 2838 : getter_AddRefs(file));
259 2838 : if (NS_FAILED(rv))
260 0 : return NULL;
261 :
262 2838 : return file.forget();
263 : }
264 :
265 : static already_AddRefed<nsILocalFile>
266 1617 : CloneAndAppend(nsILocalFile* aBase, const nsACString& append)
267 : {
268 3234 : nsCOMPtr<nsIFile> f;
269 1617 : aBase->Clone(getter_AddRefs(f));
270 1617 : if (!f)
271 0 : return NULL;
272 :
273 3234 : nsCOMPtr<nsILocalFile> lf = do_QueryInterface(f);
274 1617 : f->AppendNative(append);
275 1617 : return lf.forget();
276 : }
277 :
278 : ////////////////////////////////////////////////////////////////////////////////
279 : // nsComponentManagerImpl
280 : ////////////////////////////////////////////////////////////////////////////////
281 :
282 : nsresult
283 0 : nsComponentManagerImpl::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult)
284 : {
285 0 : if (aOuter)
286 0 : return NS_ERROR_NO_AGGREGATION;
287 :
288 0 : if (!gComponentManager)
289 0 : return NS_ERROR_FAILURE;
290 :
291 0 : return gComponentManager->QueryInterface(aIID, aResult);
292 : }
293 :
294 1419 : nsComponentManagerImpl::nsComponentManagerImpl()
295 : : mMon("nsComponentManagerImpl.mMon")
296 1419 : , mStatus(NOT_INITIALIZED)
297 : {
298 1419 : }
299 :
300 : #define CONTRACTID_HASHTABLE_INITIAL_SIZE 2048
301 :
302 : nsTArray<const mozilla::Module*>* nsComponentManagerImpl::sStaticModules;
303 :
304 : /* static */ void
305 1419 : nsComponentManagerImpl::InitializeStaticModules()
306 : {
307 1419 : if (sStaticModules)
308 0 : return;
309 :
310 1419 : sStaticModules = new nsTArray<const mozilla::Module*>;
311 78045 : for (const mozilla::Module *const *const *staticModules = kPStaticModules;
312 : *staticModules; ++staticModules)
313 76626 : sStaticModules->AppendElement(**staticModules);
314 : }
315 :
316 : nsTArray<nsComponentManagerImpl::ComponentLocation>*
317 : nsComponentManagerImpl::sModuleLocations;
318 :
319 : /* static */ void
320 3034 : nsComponentManagerImpl::InitializeModuleLocations()
321 : {
322 3034 : if (sModuleLocations)
323 1615 : return;
324 :
325 1419 : sModuleLocations = new nsTArray<ComponentLocation>;
326 : }
327 :
328 1419 : nsresult nsComponentManagerImpl::Init()
329 : {
330 : NS_TIME_FUNCTION;
331 :
332 1419 : PR_ASSERT(NOT_INITIALIZED == mStatus);
333 :
334 1419 : if (nsComponentManagerLog == nsnull)
335 : {
336 1419 : nsComponentManagerLog = PR_NewLogModule("nsComponentManager");
337 : }
338 :
339 : // Initialize our arena
340 : NS_TIME_FUNCTION_MARK("Next: init component manager arena");
341 1419 : PL_INIT_ARENA_POOL(&mArena, "ComponentManagerArena", NS_CM_BLOCK_SIZE);
342 :
343 1419 : mFactories.Init(CONTRACTID_HASHTABLE_INITIAL_SIZE);
344 1419 : mContractIDs.Init(CONTRACTID_HASHTABLE_INITIAL_SIZE);
345 1419 : mLoaderMap.Init();
346 1419 : mKnownModules.Init();
347 :
348 : nsCOMPtr<nsILocalFile> greDir =
349 2838 : GetLocationFromDirectoryService(NS_GRE_DIR);
350 : nsCOMPtr<nsILocalFile> appDir =
351 2838 : GetLocationFromDirectoryService(NS_XPCOM_CURRENT_PROCESS_DIR);
352 :
353 1419 : InitializeStaticModules();
354 1419 : InitializeModuleLocations();
355 :
356 1419 : ComponentLocation* cl = sModuleLocations->InsertElementAt(0);
357 2838 : nsCOMPtr<nsILocalFile> lf = CloneAndAppend(appDir, NS_LITERAL_CSTRING("chrome.manifest"));
358 1419 : cl->type = NS_COMPONENT_LOCATION;
359 1419 : cl->location.Init(lf);
360 :
361 1419 : bool equals = false;
362 1419 : appDir->Equals(greDir, &equals);
363 1419 : if (!equals) {
364 0 : cl = sModuleLocations->InsertElementAt(0);
365 0 : cl->type = NS_COMPONENT_LOCATION;
366 0 : lf = CloneAndAppend(greDir, NS_LITERAL_CSTRING("chrome.manifest"));
367 0 : cl->location.Init(lf);
368 : }
369 :
370 1419 : PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG,
371 : ("nsComponentManager: Initialized."));
372 :
373 : NS_TIME_FUNCTION_MARK("Next: init native module loader");
374 1419 : nsresult rv = mNativeModuleLoader.Init();
375 1419 : if (NS_FAILED(rv))
376 0 : return rv;
377 :
378 1419 : nsCategoryManager::GetSingleton()->SuppressNotifications(true);
379 :
380 1419 : RegisterModule(&kXPCOMModule, NULL);
381 :
382 78045 : for (PRUint32 i = 0; i < sStaticModules->Length(); ++i)
383 76626 : RegisterModule((*sStaticModules)[i], NULL);
384 :
385 2838 : nsRefPtr<nsZipArchive> appOmnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
386 1419 : if (appOmnijar) {
387 0 : cl = sModuleLocations->InsertElementAt(1); // Insert after greDir
388 0 : cl->type = NS_COMPONENT_LOCATION;
389 0 : cl->location.Init(appOmnijar, "chrome.manifest");
390 : }
391 2838 : nsRefPtr<nsZipArchive> greOmnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
392 1419 : if (greOmnijar) {
393 0 : cl = sModuleLocations->InsertElementAt(0);
394 0 : cl->type = NS_COMPONENT_LOCATION;
395 0 : cl->location.Init(greOmnijar, "chrome.manifest");
396 : }
397 :
398 1419 : RereadChromeManifests(false);
399 :
400 1419 : nsCategoryManager::GetSingleton()->SuppressNotifications(false);
401 :
402 1419 : mStatus = NORMAL;
403 :
404 1419 : return NS_OK;
405 : }
406 :
407 : void
408 83724 : nsComponentManagerImpl::RegisterModule(const mozilla::Module* aModule,
409 : FileLocation* aFile)
410 : {
411 167448 : ReentrantMonitorAutoEnter mon(mMon);
412 :
413 : KnownModule* m;
414 83724 : if (aFile) {
415 11358 : nsCString uri;
416 5679 : aFile->GetURIString(uri);
417 5679 : NS_ASSERTION(!mKnownModules.Get(uri),
418 : "Must not register a binary module twice.");
419 :
420 5679 : m = new KnownModule(aModule, *aFile);
421 5679 : mKnownModules.Put(uri, m);
422 : } else {
423 78045 : m = new KnownModule(aModule);
424 78045 : mKnownStaticModules.AppendElement(m);
425 : }
426 :
427 83724 : if (aModule->mCIDs) {
428 : const mozilla::Module::CIDEntry* entry;
429 1082707 : for (entry = aModule->mCIDs; entry->cid; ++entry)
430 998983 : RegisterCIDEntry(entry, m);
431 : }
432 :
433 83724 : if (aModule->mContractIDs) {
434 : const mozilla::Module::ContractIDEntry* entry;
435 1142303 : for (entry = aModule->mContractIDs; entry->contractid; ++entry)
436 1058580 : RegisterContractID(entry);
437 83723 : NS_ASSERTION(!entry->cid, "Incorrectly terminated contract list");
438 : }
439 :
440 83724 : if (aModule->mCategoryEntries) {
441 : const mozilla::Module::CategoryEntry* entry;
442 394482 : for (entry = aModule->mCategoryEntries; entry->category; ++entry)
443 : nsCategoryManager::GetSingleton()->
444 : AddCategoryEntry(entry->category,
445 : entry->entry,
446 368940 : entry->value);
447 : }
448 83724 : }
449 :
450 : void
451 998983 : nsComponentManagerImpl::RegisterCIDEntry(const mozilla::Module::CIDEntry* aEntry,
452 : KnownModule* aModule)
453 : {
454 998983 : mMon.AssertCurrentThreadIn();
455 :
456 998983 : nsFactoryEntry* f = mFactories.Get(*aEntry->cid);
457 998983 : if (f) {
458 0 : NS_WARNING("Re-registering a CID?");
459 :
460 : char idstr[NSID_LENGTH];
461 0 : aEntry->cid->ToProvidedString(idstr);
462 :
463 0 : nsCString existing;
464 0 : if (f->mModule)
465 0 : existing = f->mModule->Description();
466 : else
467 0 : existing = "<unknown module>";
468 :
469 : LogMessage("While registering XPCOM module %s, trying to re-register CID '%s' already registered by %s.",
470 0 : aModule->Description().get(),
471 : idstr,
472 0 : existing.get());
473 : return;
474 : }
475 :
476 998983 : f = new nsFactoryEntry(aEntry, aModule);
477 998983 : mFactories.Put(*aEntry->cid, f);
478 : }
479 :
480 : void
481 1058580 : nsComponentManagerImpl::RegisterContractID(const mozilla::Module::ContractIDEntry* aEntry)
482 : {
483 1058580 : mMon.AssertCurrentThreadIn();
484 :
485 1058580 : nsFactoryEntry* f = mFactories.Get(*aEntry->cid);
486 1058580 : if (!f) {
487 0 : NS_ERROR("No CID found when attempting to map contract ID");
488 :
489 : char idstr[NSID_LENGTH];
490 0 : aEntry->cid->ToProvidedString(idstr);
491 :
492 : LogMessage("Could not map contract ID '%s' to CID %s because no implementation of the CID is registered.",
493 : aEntry->contractid,
494 0 : idstr);
495 :
496 0 : return;
497 : }
498 :
499 1058580 : mContractIDs.Put(nsDependentCString(aEntry->contractid), f);
500 : }
501 :
502 : static void
503 2063 : CutExtension(nsCString& path)
504 : {
505 2063 : PRInt32 dotPos = path.RFindChar('.');
506 2063 : if (kNotFound == dotPos)
507 0 : path.Truncate();
508 : else
509 2063 : path.Cut(0, dotPos + 1);
510 2063 : }
511 :
512 : void
513 99294 : nsComponentManagerImpl::RegisterManifest(NSLocationType aType,
514 : FileLocation &aFile,
515 : bool aChromeOnly)
516 : {
517 : PRUint32 len;
518 198588 : FileLocation::Data data;
519 198588 : nsAutoArrayPtr<char> buf;
520 99294 : nsresult rv = aFile.GetData(data);
521 99294 : if (NS_SUCCEEDED(rv)) {
522 99082 : rv = data.GetSize(&len);
523 : }
524 99294 : if (NS_SUCCEEDED(rv)) {
525 198164 : buf = new char[len + 1];
526 99082 : rv = data.Copy(buf, len);
527 : }
528 99294 : if (NS_SUCCEEDED(rv)) {
529 99082 : buf[len] = '\0';
530 99082 : ParseManifest(aType, aFile, buf, aChromeOnly);
531 212 : } else if (NS_BOOTSTRAPPED_LOCATION != aType) {
532 0 : nsCString uri;
533 0 : aFile.GetURIString(uri);
534 0 : LogMessage("Could not read chrome manifest '%s'.", uri.get());
535 : }
536 99294 : }
537 :
538 : void
539 95819 : nsComponentManagerImpl::ManifestManifest(ManifestProcessingContext& cx, int lineno, char *const * argv)
540 : {
541 95819 : char* file = argv[0];
542 191638 : FileLocation f(cx.mFile, file);
543 95819 : RegisterManifest(cx.mType, f, cx.mChromeOnly);
544 95819 : }
545 :
546 : void
547 5682 : nsComponentManagerImpl::ManifestBinaryComponent(ManifestProcessingContext& cx, int lineno, char *const * argv)
548 : {
549 5682 : if (cx.mFile.IsZip()) {
550 0 : NS_WARNING("Cannot load binary components from a jar.");
551 : LogMessageWithContext(cx.mFile, lineno,
552 0 : "Cannot load binary components from a jar.");
553 0 : return;
554 : }
555 :
556 11364 : FileLocation f(cx.mFile, argv[0]);
557 11364 : nsCString uri;
558 5682 : f.GetURIString(uri);
559 :
560 5682 : if (mKnownModules.Get(uri)) {
561 2 : NS_WARNING("Attempting to register a binary component twice.");
562 : LogMessageWithContext(cx.mFile, lineno,
563 2 : "Attempting to register a binary component twice.");
564 : return;
565 : }
566 :
567 5680 : const mozilla::Module* m = mNativeModuleLoader.LoadModule(f);
568 : // The native module loader should report an error here, we don't have to
569 5680 : if (!m)
570 : return;
571 :
572 11361 : RegisterModule(m, &f);
573 : }
574 :
575 : void
576 218497 : nsComponentManagerImpl::ManifestXPT(ManifestProcessingContext& cx, int lineno, char *const * argv)
577 : {
578 436994 : FileLocation f(cx.mFile, argv[0]);
579 : PRUint32 len;
580 436994 : FileLocation::Data data;
581 436994 : nsAutoArrayPtr<char> buf;
582 218497 : nsresult rv = f.GetData(data);
583 218497 : if (NS_SUCCEEDED(rv)) {
584 218497 : rv = data.GetSize(&len);
585 : }
586 218497 : if (NS_SUCCEEDED(rv)) {
587 436994 : buf = new char[len];
588 218497 : rv = data.Copy(buf, len);
589 : }
590 218497 : if (NS_SUCCEEDED(rv)) {
591 : xptiInterfaceInfoManager::GetSingleton()
592 218497 : ->RegisterBuffer(buf, len);
593 : } else {
594 0 : nsCString uri;
595 0 : f.GetURIString(uri);
596 0 : LogMessage("Could not read '%s'.", uri.get());
597 : }
598 218497 : }
599 :
600 : void
601 136220 : nsComponentManagerImpl::ManifestComponent(ManifestProcessingContext& cx, int lineno, char *const * argv)
602 : {
603 136220 : char* id = argv[0];
604 136220 : char* file = argv[1];
605 :
606 : nsID cid;
607 136220 : if (!cid.Parse(id)) {
608 : LogMessageWithContext(cx.mFile, lineno,
609 1 : "Malformed CID: '%s'.", id);
610 1 : return;
611 : }
612 :
613 272438 : ReentrantMonitorAutoEnter mon(mMon);
614 136219 : nsFactoryEntry* f = mFactories.Get(cid);
615 136219 : if (f) {
616 : char idstr[NSID_LENGTH];
617 1387 : cid.ToProvidedString(idstr);
618 :
619 2774 : nsCString existing;
620 1387 : if (f->mModule)
621 1387 : existing = f->mModule->Description();
622 : else
623 0 : existing = "<unknown module>";
624 :
625 : LogMessageWithContext(cx.mFile, lineno,
626 : "Trying to re-register CID '%s' already registered by %s.",
627 : idstr,
628 1387 : existing.get());
629 : return;
630 : }
631 :
632 : KnownModule* km;
633 269664 : FileLocation fl(cx.mFile, file);
634 :
635 269664 : nsCString hash;
636 134832 : fl.GetURIString(hash);
637 134832 : km = mKnownModules.Get(hash);
638 134832 : if (!km) {
639 100771 : km = new KnownModule(fl);
640 100771 : mKnownModules.Put(hash, km);
641 : }
642 :
643 : void* place;
644 :
645 134832 : PL_ARENA_ALLOCATE(place, &mArena, sizeof(nsCID));
646 134832 : nsID* permanentCID = static_cast<nsID*>(place);
647 134832 : *permanentCID = cid;
648 :
649 134832 : PL_ARENA_ALLOCATE(place, &mArena, sizeof(mozilla::Module::CIDEntry));
650 134832 : mozilla::Module::CIDEntry* e = new (place) mozilla::Module::CIDEntry();
651 134832 : e->cid = permanentCID;
652 :
653 134832 : f = new nsFactoryEntry(e, km);
654 134832 : mFactories.Put(cid, f);
655 : }
656 :
657 : void
658 137637 : nsComponentManagerImpl::ManifestContract(ManifestProcessingContext& cx, int lineno, char *const * argv)
659 : {
660 137637 : char* contract = argv[0];
661 137637 : char* id = argv[1];
662 :
663 : nsID cid;
664 137637 : if (!cid.Parse(id)) {
665 : LogMessageWithContext(cx.mFile, lineno,
666 0 : "Malformed CID: '%s'.", id);
667 0 : return;
668 : }
669 :
670 275274 : ReentrantMonitorAutoEnter mon(mMon);
671 137637 : nsFactoryEntry* f = mFactories.Get(cid);
672 137637 : if (!f) {
673 : LogMessageWithContext(cx.mFile, lineno,
674 : "Could not map contract ID '%s' to CID %s because no implementation of the CID is registered.",
675 1 : contract, id);
676 : return;
677 : }
678 :
679 137636 : mContractIDs.Put(nsDependentCString(contract), f);
680 : }
681 :
682 : void
683 49675 : nsComponentManagerImpl::ManifestCategory(ManifestProcessingContext& cx, int lineno, char *const * argv)
684 : {
685 49675 : char* category = argv[0];
686 49675 : char* key = argv[1];
687 49675 : char* value = argv[2];
688 :
689 : nsCategoryManager::GetSingleton()->
690 49675 : AddCategoryEntry(category, key, value);
691 49675 : }
692 :
693 : void
694 1624 : nsComponentManagerImpl::RereadChromeManifests(bool aChromeOnly)
695 : {
696 4873 : for (PRUint32 i = 0; i < sModuleLocations->Length(); ++i) {
697 3249 : ComponentLocation& l = sModuleLocations->ElementAt(i);
698 3249 : RegisterManifest(l.type, l.location, aChromeOnly);
699 : }
700 1624 : }
701 :
702 : bool
703 2063 : nsComponentManagerImpl::KnownModule::EnsureLoader()
704 : {
705 2063 : if (!mLoader) {
706 4126 : nsCString extension;
707 2063 : mFile.GetURIString(extension);
708 2063 : CutExtension(extension);
709 2063 : mLoader = nsComponentManagerImpl::gComponentManager->LoaderForExtension(extension);
710 : }
711 2063 : return !!mLoader;
712 : }
713 :
714 : bool
715 101897 : nsComponentManagerImpl::KnownModule::Load()
716 : {
717 101897 : if (mFailed)
718 0 : return false;
719 101897 : if (!mModule) {
720 2063 : if (!EnsureLoader())
721 0 : return false;
722 :
723 2063 : mModule = mLoader->LoadModule(mFile);
724 :
725 2063 : if (!mModule) {
726 0 : mFailed = true;
727 0 : return false;
728 : }
729 : }
730 101897 : if (!mLoaded) {
731 29864 : if (mModule->loadProc) {
732 7817 : nsresult rv = mModule->loadProc();
733 7817 : if (NS_FAILED(rv)) {
734 0 : mFailed = true;
735 0 : return false;
736 : }
737 : }
738 29864 : mLoaded = true;
739 : }
740 101897 : return true;
741 : }
742 :
743 : nsCString
744 1387 : nsComponentManagerImpl::KnownModule::Description() const
745 : {
746 1387 : nsCString s;
747 1387 : if (mFile)
748 1387 : mFile.GetURIString(s);
749 : else
750 0 : s = "<static module>";
751 : return s;
752 : }
753 :
754 1419 : nsresult nsComponentManagerImpl::Shutdown(void)
755 : {
756 : NS_TIME_FUNCTION;
757 :
758 1419 : PR_ASSERT(NORMAL == mStatus);
759 :
760 1419 : mStatus = SHUTDOWN_IN_PROGRESS;
761 :
762 : // Shutdown the component manager
763 1419 : PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning Shutdown."));
764 :
765 : // Release all cached factories
766 1419 : mContractIDs.Clear();
767 1419 : mFactories.Clear(); // XXX release the objects, don't just clear
768 1419 : mLoaderMap.Clear();
769 1419 : mKnownModules.Clear();
770 1419 : mKnownStaticModules.Clear();
771 :
772 1419 : mLoaderData.Clear();
773 :
774 1419 : delete sStaticModules;
775 1419 : delete sModuleLocations;
776 :
777 : // Unload libraries
778 1419 : mNativeModuleLoader.UnloadLibraries();
779 :
780 : // delete arena for strings and small objects
781 1419 : PL_FinishArenaPool(&mArena);
782 :
783 1419 : mStatus = SHUTDOWN_COMPLETE;
784 :
785 1419 : PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Shutdown complete."));
786 :
787 1419 : return NS_OK;
788 : }
789 :
790 2838 : nsComponentManagerImpl::~nsComponentManagerImpl()
791 : {
792 1419 : PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning destruction."));
793 :
794 1419 : if (SHUTDOWN_COMPLETE != mStatus)
795 0 : Shutdown();
796 :
797 1419 : PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Destroyed."));
798 1419 : }
799 :
800 2112238 : NS_IMPL_THREADSAFE_ISUPPORTS5(nsComponentManagerImpl,
801 : nsIComponentManager,
802 : nsIServiceManager,
803 : nsIComponentRegistrar,
804 : nsISupportsWeakReference,
805 : nsIInterfaceRequestor)
806 :
807 :
808 : nsresult
809 0 : nsComponentManagerImpl::GetInterface(const nsIID & uuid, void **result)
810 : {
811 0 : NS_WARNING("This isn't supported");
812 : // fall through to QI as anything QIable is a superset of what can be
813 : // got via the GetInterface()
814 0 : return QueryInterface(uuid, result);
815 : }
816 :
817 : nsFactoryEntry *
818 479864 : nsComponentManagerImpl::GetFactoryEntry(const char *aContractID,
819 : PRUint32 aContractIDLen)
820 : {
821 959728 : ReentrantMonitorAutoEnter mon(mMon);
822 479864 : return mContractIDs.Get(nsDependentCString(aContractID, aContractIDLen));
823 : }
824 :
825 :
826 : nsFactoryEntry *
827 121680 : nsComponentManagerImpl::GetFactoryEntry(const nsCID &aClass)
828 : {
829 243360 : ReentrantMonitorAutoEnter mon(mMon);
830 121680 : return mFactories.Get(aClass);
831 : }
832 :
833 : already_AddRefed<nsIFactory>
834 2795 : nsComponentManagerImpl::FindFactory(const nsCID& aClass)
835 : {
836 2795 : nsFactoryEntry* e = GetFactoryEntry(aClass);
837 2795 : if (!e)
838 0 : return NULL;
839 :
840 2795 : return e->GetFactory();
841 : }
842 :
843 : already_AddRefed<nsIFactory>
844 14623 : nsComponentManagerImpl::FindFactory(const char *contractID,
845 : PRUint32 aContractIDLen)
846 : {
847 14623 : nsFactoryEntry *entry = GetFactoryEntry(contractID, aContractIDLen);
848 14623 : if (!entry)
849 14623 : return NULL;
850 :
851 0 : return entry->GetFactory();
852 : }
853 :
854 : /**
855 : * GetClassObject()
856 : *
857 : * Given a classID, this finds the singleton ClassObject that implements the CID.
858 : * Returns an interface of type aIID off the singleton classobject.
859 : */
860 : NS_IMETHODIMP
861 2795 : nsComponentManagerImpl::GetClassObject(const nsCID &aClass, const nsIID &aIID,
862 : void **aResult)
863 : {
864 : nsresult rv;
865 :
866 : #ifdef PR_LOGGING
867 2795 : if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_DEBUG))
868 : {
869 0 : char *buf = aClass.ToString();
870 0 : PR_LogPrint("nsComponentManager: GetClassObject(%s)", buf);
871 0 : if (buf)
872 0 : NS_Free(buf);
873 : }
874 : #endif
875 :
876 2795 : PR_ASSERT(aResult != nsnull);
877 :
878 5590 : nsCOMPtr<nsIFactory> factory = FindFactory(aClass);
879 2795 : if (!factory)
880 0 : return NS_ERROR_FACTORY_NOT_REGISTERED;
881 :
882 2795 : rv = factory->QueryInterface(aIID, aResult);
883 :
884 2795 : PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
885 : ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
886 :
887 2795 : return rv;
888 : }
889 :
890 :
891 : NS_IMETHODIMP
892 14623 : nsComponentManagerImpl::GetClassObjectByContractID(const char *contractID,
893 : const nsIID &aIID,
894 : void **aResult)
895 : {
896 14623 : NS_ENSURE_ARG_POINTER(aResult);
897 14623 : NS_ENSURE_ARG_POINTER(contractID);
898 :
899 : nsresult rv;
900 :
901 :
902 : #ifdef PR_LOGGING
903 14623 : if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_DEBUG))
904 : {
905 0 : PR_LogPrint("nsComponentManager: GetClassObject(%s)", contractID);
906 : }
907 : #endif
908 :
909 29246 : nsCOMPtr<nsIFactory> factory = FindFactory(contractID, strlen(contractID));
910 14623 : if (!factory)
911 14623 : return NS_ERROR_FACTORY_NOT_REGISTERED;
912 :
913 0 : rv = factory->QueryInterface(aIID, aResult);
914 :
915 0 : PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
916 : ("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
917 :
918 0 : return rv;
919 : }
920 :
921 : /**
922 : * CreateInstance()
923 : *
924 : * Create an instance of an object that implements an interface and belongs
925 : * to the implementation aClass using the factory. The factory is immediately
926 : * released and not held onto for any longer.
927 : */
928 : NS_IMETHODIMP
929 118881 : nsComponentManagerImpl::CreateInstance(const nsCID &aClass,
930 : nsISupports *aDelegate,
931 : const nsIID &aIID,
932 : void **aResult)
933 : {
934 : COMPMGR_TIME_FUNCTION_CID(aClass);
935 :
936 : // test this first, since there's no point in creating a component during
937 : // shutdown -- whether it's available or not would depend on the order it
938 : // occurs in the list
939 118881 : if (gXPCOMShuttingDown) {
940 : // When processing shutdown, don't process new GetService() requests
941 : #ifdef SHOW_DENIED_ON_SHUTDOWN
942 : nsXPIDLCString cid, iid;
943 : cid.Adopt(aClass.ToString());
944 : iid.Adopt(aIID.ToString());
945 : fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
946 : " CID: %s\n IID: %s\n", cid.get(), iid.get());
947 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
948 0 : return NS_ERROR_UNEXPECTED;
949 : }
950 :
951 118881 : if (aResult == nsnull)
952 : {
953 0 : return NS_ERROR_NULL_POINTER;
954 : }
955 118881 : *aResult = nsnull;
956 :
957 118881 : nsFactoryEntry *entry = GetFactoryEntry(aClass);
958 :
959 118881 : if (!entry)
960 0 : return NS_ERROR_FACTORY_NOT_REGISTERED;
961 :
962 : #ifdef SHOW_CI_ON_EXISTING_SERVICE
963 : if (entry->mServiceObject) {
964 : nsXPIDLCString cid;
965 : cid.Adopt(aClass.ToString());
966 : nsCAutoString message;
967 : message = NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
968 : cid + NS_LITERAL_CSTRING("\" when a service for this CID already exists!");
969 : NS_ERROR(message.get());
970 : }
971 : #endif
972 :
973 : nsresult rv;
974 237762 : nsCOMPtr<nsIFactory> factory = entry->GetFactory();
975 118881 : if (factory)
976 : {
977 118881 : rv = factory->CreateInstance(aDelegate, aIID, aResult);
978 118881 : if (NS_SUCCEEDED(rv) && !*aResult) {
979 0 : NS_ERROR("Factory did not return an object but returned success!");
980 0 : rv = NS_ERROR_SERVICE_NOT_FOUND;
981 : }
982 : }
983 : else {
984 : // Translate error values
985 0 : rv = NS_ERROR_FACTORY_NOT_REGISTERED;
986 : }
987 :
988 : #ifdef PR_LOGGING
989 118881 : if (PR_LOG_TEST(nsComponentManagerLog, PR_LOG_WARNING))
990 : {
991 0 : char *buf = aClass.ToString();
992 0 : PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
993 : ("nsComponentManager: CreateInstance(%s) %s", buf,
994 : NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
995 0 : if (buf)
996 0 : NS_Free(buf);
997 : }
998 : #endif
999 :
1000 118881 : return rv;
1001 : }
1002 :
1003 : /**
1004 : * CreateInstanceByContractID()
1005 : *
1006 : * A variant of CreateInstance() that creates an instance of the object that
1007 : * implements the interface aIID and whose implementation has a contractID aContractID.
1008 : *
1009 : * This is only a convenience routine that turns around can calls the
1010 : * CreateInstance() with classid and iid.
1011 : */
1012 : NS_IMETHODIMP
1013 465489 : nsComponentManagerImpl::CreateInstanceByContractID(const char *aContractID,
1014 : nsISupports *aDelegate,
1015 : const nsIID &aIID,
1016 : void **aResult)
1017 : {
1018 : COMPMGR_TIME_FUNCTION_CONTRACTID(aContractID);
1019 :
1020 465489 : NS_ENSURE_ARG_POINTER(aContractID);
1021 :
1022 : // test this first, since there's no point in creating a component during
1023 : // shutdown -- whether it's available or not would depend on the order it
1024 : // occurs in the list
1025 465489 : if (gXPCOMShuttingDown) {
1026 : // When processing shutdown, don't process new GetService() requests
1027 : #ifdef SHOW_DENIED_ON_SHUTDOWN
1028 : nsXPIDLCString iid;
1029 : iid.Adopt(aIID.ToString());
1030 : fprintf(stderr, "Creating new instance on shutdown. Denied.\n"
1031 : " ContractID: %s\n IID: %s\n", aContractID, iid.get());
1032 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
1033 248 : return NS_ERROR_UNEXPECTED;
1034 : }
1035 :
1036 465241 : if (aResult == nsnull)
1037 : {
1038 0 : return NS_ERROR_NULL_POINTER;
1039 : }
1040 465241 : *aResult = nsnull;
1041 :
1042 465241 : nsFactoryEntry *entry = GetFactoryEntry(aContractID, strlen(aContractID));
1043 :
1044 465241 : if (!entry)
1045 24 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1046 :
1047 : #ifdef SHOW_CI_ON_EXISTING_SERVICE
1048 : if (entry->mServiceObject) {
1049 : nsCAutoString message;
1050 : message =
1051 : NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
1052 : nsDependentCString(aContractID) +
1053 : NS_LITERAL_CSTRING("\" when a service for this CID already exists! "
1054 : "Add it to abusedContracts to track down the service consumer.");
1055 : NS_ERROR(message.get());
1056 : }
1057 : #endif
1058 :
1059 : nsresult rv;
1060 930434 : nsCOMPtr<nsIFactory> factory = entry->GetFactory();
1061 465217 : if (factory)
1062 : {
1063 :
1064 465217 : rv = factory->CreateInstance(aDelegate, aIID, aResult);
1065 465217 : if (NS_SUCCEEDED(rv) && !*aResult) {
1066 0 : NS_ERROR("Factory did not return an object but returned success!");
1067 0 : rv = NS_ERROR_SERVICE_NOT_FOUND;
1068 : }
1069 : }
1070 : else {
1071 : // Translate error values
1072 0 : rv = NS_ERROR_FACTORY_NOT_REGISTERED;
1073 : }
1074 :
1075 465217 : PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
1076 : ("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID,
1077 : NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
1078 :
1079 465217 : return rv;
1080 : }
1081 :
1082 : static PLDHashOperator
1083 1134257 : FreeFactoryEntries(const nsID& aCID,
1084 : nsFactoryEntry* aEntry,
1085 : void* arg)
1086 : {
1087 1134257 : aEntry->mFactory = NULL;
1088 1134257 : aEntry->mServiceObject = NULL;
1089 1134257 : return PL_DHASH_NEXT;
1090 : }
1091 :
1092 : nsresult
1093 1419 : nsComponentManagerImpl::FreeServices()
1094 : {
1095 1419 : NS_ASSERTION(gXPCOMShuttingDown, "Must be shutting down in order to free all services");
1096 :
1097 1419 : if (!gXPCOMShuttingDown)
1098 0 : return NS_ERROR_FAILURE;
1099 :
1100 1419 : mFactories.EnumerateRead(FreeFactoryEntries, NULL);
1101 1419 : return NS_OK;
1102 : }
1103 :
1104 : // This should only ever be called within the monitor!
1105 : nsComponentManagerImpl::PendingServiceInfo*
1106 77872 : nsComponentManagerImpl::AddPendingService(const nsCID& aServiceCID,
1107 : PRThread* aThread)
1108 : {
1109 77872 : PendingServiceInfo* newInfo = mPendingServices.AppendElement();
1110 77872 : if (newInfo) {
1111 77872 : newInfo->cid = &aServiceCID;
1112 77872 : newInfo->thread = aThread;
1113 : }
1114 77872 : return newInfo;
1115 : }
1116 :
1117 : // This should only ever be called within the monitor!
1118 : void
1119 77872 : nsComponentManagerImpl::RemovePendingService(const nsCID& aServiceCID)
1120 : {
1121 77872 : PRUint32 pendingCount = mPendingServices.Length();
1122 109863 : for (PRUint32 index = 0; index < pendingCount; ++index) {
1123 109863 : const PendingServiceInfo& info = mPendingServices.ElementAt(index);
1124 109863 : if (info.cid->Equals(aServiceCID)) {
1125 77872 : mPendingServices.RemoveElementAt(index);
1126 77872 : return;
1127 : }
1128 : }
1129 : }
1130 :
1131 : // This should only ever be called within the monitor!
1132 : PRThread*
1133 155744 : nsComponentManagerImpl::GetPendingServiceThread(const nsCID& aServiceCID) const
1134 : {
1135 155744 : PRUint32 pendingCount = mPendingServices.Length();
1136 219726 : for (PRUint32 index = 0; index < pendingCount; ++index) {
1137 141854 : const PendingServiceInfo& info = mPendingServices.ElementAt(index);
1138 141854 : if (info.cid->Equals(aServiceCID)) {
1139 77872 : return info.thread;
1140 : }
1141 : }
1142 77872 : return nsnull;
1143 : }
1144 :
1145 : // GetService() wants to manually Exit()/Enter() a monitor which is
1146 : // wrapped in ReentrantMonitorAutoEnter, which nsAutoReentrantMonitor used to allow.
1147 : // One use is block-scoped Exit()/Enter(), which could be supported
1148 : // with something like a MonitoAutoExit, but that's not a well-defined
1149 : // operation in general so that helper doesn't exist. The other use
1150 : // is early-Exit() for perf reasons. This code is probably hot enough
1151 : // to warrant special considerations.
1152 : //
1153 : // We could use bare mozilla::ReentrantMonitor, but that's error prone.
1154 : // Instead, we just add a hacky wrapper here that acts like the old
1155 : // nsAutoReentrantMonitor.
1156 : struct NS_STACK_CLASS AutoReentrantMonitor
1157 : {
1158 834867 : AutoReentrantMonitor(ReentrantMonitor& aReentrantMonitor) : mReentrantMonitor(&aReentrantMonitor), mEnterCount(0)
1159 : {
1160 834867 : Enter();
1161 834867 : }
1162 :
1163 834867 : ~AutoReentrantMonitor()
1164 : {
1165 834867 : if (mEnterCount) {
1166 101175 : Exit();
1167 : }
1168 834867 : }
1169 :
1170 912739 : void Enter()
1171 : {
1172 912739 : mReentrantMonitor->Enter();
1173 912739 : ++mEnterCount;
1174 912739 : }
1175 :
1176 912739 : void Exit()
1177 : {
1178 912739 : --mEnterCount;
1179 912739 : mReentrantMonitor->Exit();
1180 912739 : }
1181 :
1182 : ReentrantMonitor* mReentrantMonitor;
1183 : PRInt32 mEnterCount;
1184 : };
1185 :
1186 : NS_IMETHODIMP
1187 91250 : nsComponentManagerImpl::GetService(const nsCID& aClass,
1188 : const nsIID& aIID,
1189 : void* *result)
1190 : {
1191 : // test this first, since there's no point in returning a service during
1192 : // shutdown -- whether it's available or not would depend on the order it
1193 : // occurs in the list
1194 91250 : if (gXPCOMShuttingDown) {
1195 : // When processing shutdown, don't process new GetService() requests
1196 : #ifdef SHOW_DENIED_ON_SHUTDOWN
1197 : nsXPIDLCString cid, iid;
1198 : cid.Adopt(aClass.ToString());
1199 : iid.Adopt(aIID.ToString());
1200 : fprintf(stderr, "Getting service on shutdown. Denied.\n"
1201 : " CID: %s\n IID: %s\n", cid.get(), iid.get());
1202 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
1203 281 : return NS_ERROR_UNEXPECTED;
1204 : }
1205 :
1206 181938 : AutoReentrantMonitor mon(mMon);
1207 :
1208 90969 : nsFactoryEntry* entry = mFactories.Get(aClass);
1209 90969 : if (!entry)
1210 0 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1211 :
1212 90969 : if (entry->mServiceObject) {
1213 167870 : nsCOMPtr<nsISupports> supports = entry->mServiceObject;
1214 83935 : mon.Exit();
1215 83935 : return supports->QueryInterface(aIID, result);
1216 : }
1217 :
1218 : // We only care about time when we create the service.
1219 : COMPMGR_TIME_FUNCTION_CID(aClass);
1220 :
1221 7034 : PRThread* currentPRThread = PR_GetCurrentThread();
1222 7034 : NS_ASSERTION(currentPRThread, "This should never be null!");
1223 :
1224 : // Needed to optimize the event loop below.
1225 7034 : nsIThread* currentThread = nsnull;
1226 :
1227 : PRThread* pendingPRThread;
1228 14068 : while ((pendingPRThread = GetPendingServiceThread(aClass))) {
1229 0 : if (pendingPRThread == currentPRThread) {
1230 0 : NS_ERROR("Recursive GetService!");
1231 0 : return NS_ERROR_NOT_AVAILABLE;
1232 : }
1233 :
1234 0 : mon.Exit();
1235 :
1236 0 : if (!currentThread) {
1237 0 : currentThread = NS_GetCurrentThread();
1238 0 : NS_ASSERTION(currentThread, "This should never be null!");
1239 : }
1240 :
1241 : // This will process a single event or yield the thread if no event is
1242 : // pending.
1243 0 : if (!NS_ProcessNextEvent(currentThread, false)) {
1244 0 : PR_Sleep(PR_INTERVAL_NO_WAIT);
1245 : }
1246 :
1247 0 : mon.Enter();
1248 : }
1249 :
1250 : // It's still possible that the other thread failed to create the
1251 : // service so we're not guaranteed to have an entry or service yet.
1252 7034 : if (entry->mServiceObject) {
1253 0 : nsCOMPtr<nsISupports> supports = entry->mServiceObject;
1254 0 : mon.Exit();
1255 0 : return supports->QueryInterface(aIID, result);
1256 : }
1257 :
1258 : #ifdef DEBUG
1259 : PendingServiceInfo* newInfo =
1260 : #endif
1261 7034 : AddPendingService(aClass, currentPRThread);
1262 7034 : NS_ASSERTION(newInfo, "Failed to add info to the array!");
1263 :
1264 14068 : nsCOMPtr<nsISupports> service;
1265 : // We need to not be holding the service manager's monitor while calling
1266 : // CreateInstance, because it invokes user code which could try to re-enter
1267 : // the service manager:
1268 7034 : mon.Exit();
1269 :
1270 7034 : nsresult rv = CreateInstance(aClass, nsnull, aIID, getter_AddRefs(service));
1271 :
1272 7034 : mon.Enter();
1273 :
1274 : #ifdef DEBUG
1275 7034 : pendingPRThread = GetPendingServiceThread(aClass);
1276 7034 : NS_ASSERTION(pendingPRThread == currentPRThread,
1277 : "Pending service array has been changed!");
1278 : #endif
1279 7034 : RemovePendingService(aClass);
1280 :
1281 7034 : if (NS_FAILED(rv))
1282 1 : return rv;
1283 :
1284 7033 : NS_ASSERTION(!entry->mServiceObject, "Created two instances of a service!");
1285 :
1286 7033 : entry->mServiceObject = service;
1287 7033 : *result = service.get();
1288 7033 : if (!*result) {
1289 0 : NS_ERROR("Factory did not return an object but returned success!");
1290 0 : return NS_ERROR_SERVICE_NOT_FOUND;
1291 : }
1292 7033 : NS_ADDREF(static_cast<nsISupports*>((*result)));
1293 7033 : return rv;
1294 : }
1295 :
1296 : NS_IMETHODIMP
1297 0 : nsComponentManagerImpl::IsServiceInstantiated(const nsCID & aClass,
1298 : const nsIID& aIID,
1299 : bool *result)
1300 : {
1301 : COMPMGR_TIME_FUNCTION_CID(aClass);
1302 :
1303 : // Now we want to get the service if we already got it. If not, we don't want
1304 : // to create an instance of it. mmh!
1305 :
1306 : // test this first, since there's no point in returning a service during
1307 : // shutdown -- whether it's available or not would depend on the order it
1308 : // occurs in the list
1309 0 : if (gXPCOMShuttingDown) {
1310 : // When processing shutdown, don't process new GetService() requests
1311 : #ifdef SHOW_DENIED_ON_SHUTDOWN
1312 : nsXPIDLCString cid, iid;
1313 : cid.Adopt(aClass.ToString());
1314 : iid.Adopt(aIID.ToString());
1315 : fprintf(stderr, "Checking for service on shutdown. Denied.\n"
1316 : " CID: %s\n IID: %s\n", cid.get(), iid.get());
1317 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
1318 0 : return NS_ERROR_UNEXPECTED;
1319 : }
1320 :
1321 0 : nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
1322 : nsFactoryEntry* entry;
1323 :
1324 : {
1325 0 : ReentrantMonitorAutoEnter mon(mMon);
1326 0 : entry = mFactories.Get(aClass);
1327 : }
1328 :
1329 0 : if (entry && entry->mServiceObject) {
1330 0 : nsCOMPtr<nsISupports> service;
1331 0 : rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
1332 0 : *result = (service!=nsnull);
1333 : }
1334 :
1335 0 : return rv;
1336 : }
1337 :
1338 0 : NS_IMETHODIMP nsComponentManagerImpl::IsServiceInstantiatedByContractID(const char *aContractID,
1339 : const nsIID& aIID,
1340 : bool *result)
1341 : {
1342 : COMPMGR_TIME_FUNCTION_CONTRACTID(aContractID);
1343 :
1344 : // Now we want to get the service if we already got it. If not, we don't want
1345 : // to create an instance of it. mmh!
1346 :
1347 : // test this first, since there's no point in returning a service during
1348 : // shutdown -- whether it's available or not would depend on the order it
1349 : // occurs in the list
1350 0 : if (gXPCOMShuttingDown) {
1351 : // When processing shutdown, don't process new GetService() requests
1352 : #ifdef SHOW_DENIED_ON_SHUTDOWN
1353 : nsXPIDLCString iid;
1354 : iid.Adopt(aIID.ToString());
1355 : fprintf(stderr, "Checking for service on shutdown. Denied.\n"
1356 : " ContractID: %s\n IID: %s\n", aContractID, iid.get());
1357 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
1358 0 : return NS_ERROR_UNEXPECTED;
1359 : }
1360 :
1361 0 : nsresult rv = NS_ERROR_SERVICE_NOT_AVAILABLE;
1362 : nsFactoryEntry *entry;
1363 : {
1364 0 : ReentrantMonitorAutoEnter mon(mMon);
1365 0 : entry = mContractIDs.Get(nsDependentCString(aContractID));
1366 : }
1367 :
1368 0 : if (entry && entry->mServiceObject) {
1369 0 : nsCOMPtr<nsISupports> service;
1370 0 : rv = entry->mServiceObject->QueryInterface(aIID, getter_AddRefs(service));
1371 0 : *result = (service!=nsnull);
1372 : }
1373 0 : return rv;
1374 : }
1375 :
1376 :
1377 : NS_IMETHODIMP
1378 763695 : nsComponentManagerImpl::GetServiceByContractID(const char* aContractID,
1379 : const nsIID& aIID,
1380 : void* *result)
1381 : {
1382 : // test this first, since there's no point in returning a service during
1383 : // shutdown -- whether it's available or not would depend on the order it
1384 : // occurs in the list
1385 763695 : if (gXPCOMShuttingDown) {
1386 : // When processing shutdown, don't process new GetService() requests
1387 : #ifdef SHOW_DENIED_ON_SHUTDOWN
1388 : nsXPIDLCString iid;
1389 : iid.Adopt(aIID.ToString());
1390 : fprintf(stderr, "Getting service on shutdown. Denied.\n"
1391 : " ContractID: %s\n IID: %s\n", aContractID, iid.get());
1392 : #endif /* SHOW_DENIED_ON_SHUTDOWN */
1393 19797 : return NS_ERROR_UNEXPECTED;
1394 : }
1395 :
1396 1487796 : AutoReentrantMonitor mon(mMon);
1397 :
1398 743898 : nsFactoryEntry *entry = mContractIDs.Get(nsDependentCString(aContractID));
1399 743898 : if (!entry)
1400 23303 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1401 :
1402 720595 : if (entry->mServiceObject) {
1403 1299514 : nsCOMPtr<nsISupports> serviceObject = entry->mServiceObject;
1404 :
1405 : // We need to not be holding the service manager's monitor while calling
1406 : // QueryInterface, because it invokes user code which could try to re-enter
1407 : // the service manager, or try to grab some other lock/monitor/condvar
1408 : // and deadlock, e.g. bug 282743.
1409 649757 : mon.Exit();
1410 649757 : return serviceObject->QueryInterface(aIID, result);
1411 : }
1412 :
1413 : // We only care about time when we create the service.
1414 : COMPMGR_TIME_FUNCTION_CONTRACTID(aContractID);
1415 :
1416 70838 : PRThread* currentPRThread = PR_GetCurrentThread();
1417 70838 : NS_ASSERTION(currentPRThread, "This should never be null!");
1418 :
1419 : // Needed to optimize the event loop below.
1420 70838 : nsIThread* currentThread = nsnull;
1421 :
1422 : PRThread* pendingPRThread;
1423 141676 : while ((pendingPRThread = GetPendingServiceThread(*entry->mCIDEntry->cid))) {
1424 0 : if (pendingPRThread == currentPRThread) {
1425 0 : NS_ERROR("Recursive GetService!");
1426 0 : return NS_ERROR_NOT_AVAILABLE;
1427 : }
1428 :
1429 0 : mon.Exit();
1430 :
1431 0 : if (!currentThread) {
1432 0 : currentThread = NS_GetCurrentThread();
1433 0 : NS_ASSERTION(currentThread, "This should never be null!");
1434 : }
1435 :
1436 : // This will process a single event or yield the thread if no event is
1437 : // pending.
1438 0 : if (!NS_ProcessNextEvent(currentThread, false)) {
1439 0 : PR_Sleep(PR_INTERVAL_NO_WAIT);
1440 : }
1441 :
1442 0 : mon.Enter();
1443 : }
1444 :
1445 70838 : if (currentThread && entry->mServiceObject) {
1446 : // If we have a currentThread then we must have waited on another thread
1447 : // to create the service. Grab it now if that succeeded.
1448 0 : nsCOMPtr<nsISupports> serviceObject = entry->mServiceObject;
1449 0 : mon.Exit();
1450 0 : return serviceObject->QueryInterface(aIID, result);
1451 : }
1452 :
1453 : #ifdef DEBUG
1454 : PendingServiceInfo* newInfo =
1455 : #endif
1456 70838 : AddPendingService(*entry->mCIDEntry->cid, currentPRThread);
1457 70838 : NS_ASSERTION(newInfo, "Failed to add info to the array!");
1458 :
1459 141676 : nsCOMPtr<nsISupports> service;
1460 : // We need to not be holding the service manager's monitor while calling
1461 : // CreateInstance, because it invokes user code which could try to re-enter
1462 : // the service manager:
1463 70838 : mon.Exit();
1464 :
1465 : nsresult rv = CreateInstanceByContractID(aContractID, nsnull, aIID,
1466 70838 : getter_AddRefs(service));
1467 :
1468 70838 : mon.Enter();
1469 :
1470 : #ifdef DEBUG
1471 70838 : pendingPRThread = GetPendingServiceThread(*entry->mCIDEntry->cid);
1472 70838 : NS_ASSERTION(pendingPRThread == currentPRThread,
1473 : "Pending service array has been changed!");
1474 : #endif
1475 70838 : RemovePendingService(*entry->mCIDEntry->cid);
1476 :
1477 70838 : if (NS_FAILED(rv))
1478 8561 : return rv;
1479 :
1480 62277 : NS_ASSERTION(!entry->mServiceObject, "Created two instances of a service!");
1481 :
1482 62277 : entry->mServiceObject = service;
1483 62277 : *result = service.get();
1484 62277 : NS_ADDREF(static_cast<nsISupports*>(*result));
1485 62277 : return rv;
1486 : }
1487 :
1488 : already_AddRefed<mozilla::ModuleLoader>
1489 2063 : nsComponentManagerImpl::LoaderForExtension(const nsACString& aExt)
1490 : {
1491 4126 : nsCOMPtr<mozilla::ModuleLoader> loader = mLoaderMap.Get(aExt);
1492 2063 : if (!loader) {
1493 : loader = do_GetServiceFromCategory("module-loader",
1494 759 : PromiseFlatCString(aExt).get());
1495 759 : if (!loader)
1496 0 : return NULL;
1497 :
1498 759 : mLoaderMap.Put(aExt, loader);
1499 : }
1500 :
1501 2063 : return loader.forget();
1502 : }
1503 :
1504 : NS_IMETHODIMP
1505 3261 : nsComponentManagerImpl::RegisterFactory(const nsCID& aClass,
1506 : const char* aName,
1507 : const char* aContractID,
1508 : nsIFactory* aFactory)
1509 : {
1510 3261 : if (!aFactory) {
1511 : // If a null factory is passed in, this call just wants to reset
1512 : // the contract ID to point to an existing CID entry.
1513 1 : if (!aContractID)
1514 0 : return NS_ERROR_INVALID_ARG;
1515 :
1516 2 : ReentrantMonitorAutoEnter mon(mMon);
1517 1 : nsFactoryEntry* oldf = mFactories.Get(aClass);
1518 1 : if (!oldf)
1519 0 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1520 :
1521 1 : mContractIDs.Put(nsDependentCString(aContractID), oldf);
1522 1 : return NS_OK;
1523 : }
1524 :
1525 6520 : nsAutoPtr<nsFactoryEntry> f(new nsFactoryEntry(aClass, aFactory));
1526 :
1527 6520 : ReentrantMonitorAutoEnter mon(mMon);
1528 3260 : nsFactoryEntry* oldf = mFactories.Get(aClass);
1529 3260 : if (oldf)
1530 0 : return NS_ERROR_FACTORY_EXISTS;
1531 :
1532 3260 : if (aContractID)
1533 3260 : mContractIDs.Put(nsDependentCString(aContractID), f);
1534 :
1535 3260 : mFactories.Put(aClass, f.forget());
1536 :
1537 3260 : return NS_OK;
1538 : }
1539 :
1540 : NS_IMETHODIMP
1541 2818 : nsComponentManagerImpl::UnregisterFactory(const nsCID& aClass,
1542 : nsIFactory* aFactory)
1543 : {
1544 : // Don't release the dying factory or service object until releasing
1545 : // the component manager monitor.
1546 5636 : nsCOMPtr<nsIFactory> dyingFactory;
1547 5636 : nsCOMPtr<nsISupports> dyingServiceObject;
1548 :
1549 : {
1550 5636 : ReentrantMonitorAutoEnter mon(mMon);
1551 2818 : nsFactoryEntry* f = mFactories.Get(aClass);
1552 2818 : if (!f || f->mFactory != aFactory)
1553 0 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1554 :
1555 2818 : mFactories.Remove(aClass);
1556 :
1557 : // This might leave a stale contractid -> factory mapping in
1558 : // place, so null out the factory entry (see
1559 : // nsFactoryEntry::GetFactory)
1560 2818 : f->mFactory.swap(dyingFactory);
1561 5636 : f->mServiceObject.swap(dyingServiceObject);
1562 : }
1563 :
1564 2818 : return NS_OK;
1565 : }
1566 :
1567 : NS_IMETHODIMP
1568 30 : nsComponentManagerImpl::AutoRegister(nsIFile* aLocation)
1569 : {
1570 60 : nsCOMPtr<nsILocalFile> lf = do_QueryInterface(aLocation);
1571 30 : if (!lf)
1572 0 : return NS_ERROR_INVALID_ARG;
1573 :
1574 30 : XRE_AddManifestLocation(NS_COMPONENT_LOCATION, lf);
1575 30 : return NS_OK;
1576 : }
1577 :
1578 : NS_IMETHODIMP
1579 0 : nsComponentManagerImpl::AutoUnregister(nsIFile* aLocation)
1580 : {
1581 0 : NS_ERROR("AutoUnregister not implemented.");
1582 0 : return NS_ERROR_NOT_IMPLEMENTED;
1583 : }
1584 :
1585 : NS_IMETHODIMP
1586 0 : nsComponentManagerImpl::RegisterFactoryLocation(const nsCID& aCID,
1587 : const char* aClassName,
1588 : const char* aContractID,
1589 : nsIFile* aFile,
1590 : const char* aLoaderStr,
1591 : const char* aType)
1592 : {
1593 0 : NS_ERROR("RegisterFactoryLocation not implemented.");
1594 0 : return NS_ERROR_NOT_IMPLEMENTED;
1595 : }
1596 :
1597 : NS_IMETHODIMP
1598 0 : nsComponentManagerImpl::UnregisterFactoryLocation(const nsCID& aCID,
1599 : nsIFile* aFile)
1600 : {
1601 0 : NS_ERROR("UnregisterFactoryLocation not implemented.");
1602 0 : return NS_ERROR_NOT_IMPLEMENTED;
1603 : }
1604 :
1605 : NS_IMETHODIMP
1606 4 : nsComponentManagerImpl::IsCIDRegistered(const nsCID & aClass,
1607 : bool *_retval)
1608 : {
1609 4 : *_retval = (nsnull != GetFactoryEntry(aClass));
1610 4 : return NS_OK;
1611 : }
1612 :
1613 : NS_IMETHODIMP
1614 0 : nsComponentManagerImpl::IsContractIDRegistered(const char *aClass,
1615 : bool *_retval)
1616 : {
1617 0 : NS_ENSURE_ARG_POINTER(aClass);
1618 0 : nsFactoryEntry *entry = GetFactoryEntry(aClass, strlen(aClass));
1619 :
1620 0 : if (entry)
1621 0 : *_retval = true;
1622 : else
1623 0 : *_retval = false;
1624 0 : return NS_OK;
1625 : }
1626 :
1627 : static PLDHashOperator
1628 0 : EnumerateCIDHelper(const nsID& id, nsFactoryEntry* entry, void* closure)
1629 : {
1630 0 : nsCOMArray<nsISupports> *array = static_cast<nsCOMArray<nsISupports>*>(closure);
1631 0 : nsCOMPtr<nsISupportsID> wrapper = new nsSupportsIDImpl();
1632 0 : wrapper->SetData(&id);
1633 0 : array->AppendObject(wrapper);
1634 0 : return PL_DHASH_NEXT;
1635 : }
1636 :
1637 : NS_IMETHODIMP
1638 0 : nsComponentManagerImpl::EnumerateCIDs(nsISimpleEnumerator **aEnumerator)
1639 : {
1640 : NS_TIME_FUNCTION;
1641 :
1642 0 : nsCOMArray<nsISupports> array;
1643 0 : mFactories.EnumerateRead(EnumerateCIDHelper, &array);
1644 :
1645 0 : return NS_NewArrayEnumerator(aEnumerator, array);
1646 : }
1647 :
1648 : static PLDHashOperator
1649 0 : EnumerateContractsHelper(const nsACString& contract, nsFactoryEntry* entry, void* closure)
1650 : {
1651 0 : nsTArray<nsCString>* array = static_cast<nsTArray<nsCString>*>(closure);
1652 0 : array->AppendElement(contract);
1653 0 : return PL_DHASH_NEXT;
1654 : }
1655 :
1656 : NS_IMETHODIMP
1657 0 : nsComponentManagerImpl::EnumerateContractIDs(nsISimpleEnumerator **aEnumerator)
1658 : {
1659 : NS_TIME_FUNCTION;
1660 :
1661 0 : nsTArray<nsCString>* array = new nsTArray<nsCString>;
1662 0 : mContractIDs.EnumerateRead(EnumerateContractsHelper, array);
1663 :
1664 0 : nsCOMPtr<nsIUTF8StringEnumerator> e;
1665 0 : nsresult rv = NS_NewAdoptingUTF8StringEnumerator(getter_AddRefs(e), array);
1666 0 : if (NS_FAILED(rv))
1667 0 : return rv;
1668 :
1669 0 : return CallQueryInterface(e, aEnumerator);
1670 : }
1671 :
1672 : NS_IMETHODIMP
1673 0 : nsComponentManagerImpl::CIDToContractID(const nsCID & aClass,
1674 : char **_retval)
1675 : {
1676 0 : NS_ERROR("CIDTOContractID not implemented");
1677 0 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1678 : }
1679 :
1680 : NS_IMETHODIMP
1681 53359 : nsComponentManagerImpl::ContractIDToCID(const char *aContractID,
1682 : nsCID * *_retval)
1683 : {
1684 : {
1685 106718 : ReentrantMonitorAutoEnter mon(mMon);
1686 53359 : nsFactoryEntry* entry = mContractIDs.Get(nsDependentCString(aContractID));
1687 53359 : if (entry) {
1688 51775 : *_retval = (nsCID*) NS_Alloc(sizeof(nsCID));
1689 51775 : **_retval = *entry->mCIDEntry->cid;
1690 51775 : return NS_OK;
1691 : }
1692 : }
1693 1584 : *_retval = NULL;
1694 1584 : return NS_ERROR_FACTORY_NOT_REGISTERED;
1695 : }
1696 :
1697 : ////////////////////////////////////////////////////////////////////////////////
1698 : // nsFactoryEntry
1699 : ////////////////////////////////////////////////////////////////////////////////
1700 :
1701 1133815 : nsFactoryEntry::nsFactoryEntry(const mozilla::Module::CIDEntry* entry,
1702 : nsComponentManagerImpl::KnownModule* module)
1703 : : mCIDEntry(entry)
1704 1133815 : , mModule(module)
1705 : {
1706 1133815 : }
1707 :
1708 3260 : nsFactoryEntry::nsFactoryEntry(const nsCID& aCID, nsIFactory* factory)
1709 : : mCIDEntry(NULL)
1710 : , mModule(NULL)
1711 3260 : , mFactory(factory)
1712 : {
1713 3260 : mozilla::Module::CIDEntry* e = new mozilla::Module::CIDEntry();
1714 3260 : nsCID* cid = new nsCID;
1715 3260 : *cid = aCID;
1716 3260 : e->cid = cid;
1717 3260 : mCIDEntry = e;
1718 3260 : }
1719 :
1720 0 : nsFactoryEntry::~nsFactoryEntry()
1721 : {
1722 : // If this was a RegisterFactory entry, we own the CIDEntry/CID
1723 0 : if (!mModule) {
1724 0 : delete mCIDEntry->cid;
1725 0 : delete mCIDEntry;
1726 : }
1727 0 : }
1728 :
1729 : already_AddRefed<nsIFactory>
1730 586893 : nsFactoryEntry::GetFactory()
1731 : {
1732 586893 : if (!mFactory) {
1733 : // RegisterFactory then UnregisterFactory can leave an entry in mContractIDs
1734 : // pointing to an unusable nsFactoryEntry.
1735 101897 : if (!mModule)
1736 0 : return NULL;
1737 :
1738 101897 : if (!mModule->Load())
1739 0 : return NULL;
1740 :
1741 101897 : if (mModule->Module()->getFactoryProc) {
1742 4236 : mFactory = mModule->Module()->getFactoryProc(*mModule->Module(),
1743 4236 : *mCIDEntry);
1744 : }
1745 99779 : else if (mCIDEntry->getFactoryProc) {
1746 147 : mFactory = mCIDEntry->getFactoryProc(*mModule->Module(), *mCIDEntry);
1747 : }
1748 : else {
1749 99632 : NS_ASSERTION(mCIDEntry->constructorProc, "no getfactory or constructor");
1750 99632 : mFactory = new mozilla::GenericFactory(mCIDEntry->constructorProc);
1751 : }
1752 101897 : if (!mFactory)
1753 0 : return NULL;
1754 : }
1755 586893 : nsIFactory* factory = mFactory.get();
1756 586893 : NS_ADDREF(factory);
1757 586893 : return factory;
1758 : }
1759 :
1760 : ////////////////////////////////////////////////////////////////////////////////
1761 : // Static Access Functions
1762 : ////////////////////////////////////////////////////////////////////////////////
1763 :
1764 : nsresult
1765 106679 : NS_GetComponentManager(nsIComponentManager* *result)
1766 : {
1767 106679 : if (!nsComponentManagerImpl::gComponentManager)
1768 1 : return NS_ERROR_NOT_INITIALIZED;
1769 :
1770 106678 : NS_ADDREF(*result = nsComponentManagerImpl::gComponentManager);
1771 106678 : return NS_OK;
1772 : }
1773 :
1774 : nsresult
1775 247707 : NS_GetServiceManager(nsIServiceManager* *result)
1776 : {
1777 247707 : if (!nsComponentManagerImpl::gComponentManager)
1778 0 : return NS_ERROR_NOT_INITIALIZED;
1779 :
1780 247707 : NS_ADDREF(*result = nsComponentManagerImpl::gComponentManager);
1781 247707 : return NS_OK;
1782 : }
1783 :
1784 :
1785 : nsresult
1786 48125 : NS_GetComponentRegistrar(nsIComponentRegistrar* *result)
1787 : {
1788 48125 : if (!nsComponentManagerImpl::gComponentManager)
1789 0 : return NS_ERROR_NOT_INITIALIZED;
1790 :
1791 48125 : NS_ADDREF(*result = nsComponentManagerImpl::gComponentManager);
1792 48125 : return NS_OK;
1793 : }
1794 :
1795 : EXPORT_XPCOM_API(nsresult)
1796 0 : XRE_AddStaticComponent(const mozilla::Module* aComponent)
1797 : {
1798 0 : nsComponentManagerImpl::InitializeStaticModules();
1799 0 : nsComponentManagerImpl::sStaticModules->AppendElement(aComponent);
1800 :
1801 0 : if (nsComponentManagerImpl::gComponentManager &&
1802 : nsComponentManagerImpl::NORMAL == nsComponentManagerImpl::gComponentManager->mStatus)
1803 0 : nsComponentManagerImpl::gComponentManager->RegisterModule(aComponent, NULL);
1804 :
1805 0 : return NS_OK;
1806 : }
1807 :
1808 : NS_IMETHODIMP
1809 196 : nsComponentManagerImpl::AddBootstrappedManifestLocation(nsILocalFile* aLocation)
1810 : {
1811 392 : nsString path;
1812 196 : nsresult rv = aLocation->GetPath(path);
1813 196 : if (NS_FAILED(rv))
1814 0 : return rv;
1815 :
1816 196 : if (Substring(path, path.Length() - 4).Equals(NS_LITERAL_STRING(".xpi"))) {
1817 97 : return XRE_AddJarManifestLocation(NS_BOOTSTRAPPED_LOCATION, aLocation);
1818 : }
1819 :
1820 : nsCOMPtr<nsILocalFile> manifest =
1821 198 : CloneAndAppend(aLocation, NS_LITERAL_CSTRING("chrome.manifest"));
1822 99 : return XRE_AddManifestLocation(NS_BOOTSTRAPPED_LOCATION, manifest);
1823 : }
1824 :
1825 : NS_IMETHODIMP
1826 196 : nsComponentManagerImpl::RemoveBootstrappedManifestLocation(nsILocalFile* aLocation)
1827 : {
1828 392 : nsCOMPtr<nsIChromeRegistry> cr = mozilla::services::GetChromeRegistryService();
1829 196 : if (!cr)
1830 0 : return NS_ERROR_FAILURE;
1831 :
1832 392 : nsCOMPtr<nsILocalFile> manifest;
1833 392 : nsString path;
1834 196 : nsresult rv = aLocation->GetPath(path);
1835 196 : if (NS_FAILED(rv))
1836 0 : return rv;
1837 :
1838 392 : nsComponentManagerImpl::ComponentLocation elem;
1839 196 : elem.type = NS_BOOTSTRAPPED_LOCATION;
1840 :
1841 196 : if (Substring(path, path.Length() - 4).Equals(NS_LITERAL_STRING(".xpi"))) {
1842 97 : elem.location.Init(aLocation, "chrome.manifest");
1843 : } else {
1844 198 : nsCOMPtr<nsILocalFile> lf = CloneAndAppend(aLocation, NS_LITERAL_CSTRING("chrome.manifest"));
1845 99 : elem.location.Init(lf);
1846 : }
1847 :
1848 : // Remove reference.
1849 196 : nsComponentManagerImpl::sModuleLocations->RemoveElement(elem, ComponentLocationComparator());
1850 :
1851 196 : rv = cr->CheckForNewChrome();
1852 196 : return rv;
1853 : }
1854 :
1855 : EXPORT_XPCOM_API(nsresult)
1856 1517 : XRE_AddManifestLocation(NSLocationType aType, nsILocalFile* aLocation)
1857 : {
1858 1517 : nsComponentManagerImpl::InitializeModuleLocations();
1859 : nsComponentManagerImpl::ComponentLocation* c =
1860 1517 : nsComponentManagerImpl::sModuleLocations->AppendElement();
1861 1517 : c->type = aType;
1862 1517 : c->location.Init(aLocation);
1863 :
1864 1517 : if (nsComponentManagerImpl::gComponentManager &&
1865 : nsComponentManagerImpl::NORMAL == nsComponentManagerImpl::gComponentManager->mStatus)
1866 129 : nsComponentManagerImpl::gComponentManager->RegisterManifest(aType, c->location, false);
1867 :
1868 1517 : return NS_OK;
1869 : }
1870 :
1871 : EXPORT_XPCOM_API(nsresult)
1872 98 : XRE_AddJarManifestLocation(NSLocationType aType, nsILocalFile* aLocation)
1873 : {
1874 98 : nsComponentManagerImpl::InitializeModuleLocations();
1875 : nsComponentManagerImpl::ComponentLocation* c =
1876 98 : nsComponentManagerImpl::sModuleLocations->AppendElement();
1877 :
1878 98 : c->type = aType;
1879 98 : c->location.Init(aLocation, "chrome.manifest");
1880 :
1881 98 : if (nsComponentManagerImpl::gComponentManager &&
1882 : nsComponentManagerImpl::NORMAL == nsComponentManagerImpl::gComponentManager->mStatus)
1883 97 : nsComponentManagerImpl::gComponentManager->RegisterManifest(aType, c->location, false);
1884 :
1885 98 : return NS_OK;
1886 : }
1887 :
|