VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/build/nsXPComInit.cpp@ 101957

Last change on this file since 101957 was 101944, checked in by vboxsync, 15 months ago

libs/xpcom: Convert xcDll.{cpp,h} and nsLocalFileUnix.cpp to use our RTLdr* API directly instead of going through the API defined in prlink.h (which is also just using RTLdr* internally), bugref:10545

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.7 KB
Line 
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#include "nsXPCOM.h"
39#include "nsXPCOMPrivate.h"
40#include "nscore.h"
41#include "nsCOMPtr.h"
42#include "nsObserverList.h"
43#include "nsObserverService.h"
44#include "nsProperties.h"
45#include "nsIProperties.h"
46#include "nsScriptableInputStream.h"
47#include "nsBinaryStream.h"
48
49#include "nsDebugImpl.h"
50#include "nsTraceRefcntImpl.h"
51#include "nsErrorService.h"
52
53#include "nsSupportsArray.h"
54#include "nsArray.h"
55#include "nsSupportsPrimitives.h"
56#include "nsExceptionService.h"
57
58#include "nsComponentManager.h"
59#include "nsCategoryManagerUtils.h"
60#include "nsIServiceManager.h"
61#include "nsGenericFactory.h"
62
63#include "nsEventQueueService.h"
64#include "nsEventQueue.h"
65#ifdef VBOX
66# include "nsEventQueueUtils.h"
67# include "nsProxyRelease.h"
68#endif /* VBOX */
69
70#include "nsIProxyObjectManager.h"
71#include "nsProxyEventPrivate.h" // access to the impl of nsProxyObjectManager for the generic factory registration.
72
73#include "xptinfo.h"
74#include "nsIInterfaceInfoManager.h"
75
76#include "nsThread.h"
77
78#include "nsEmptyEnumerator.h"
79
80#include "nsILocalFile.h"
81#include "nsLocalFile.h"
82#if defined(XP_UNIX) || defined(XP_OS2)
83#include "nsNativeCharsetUtils.h"
84#endif
85#include "nsDirectoryService.h"
86#include "nsDirectoryServiceDefs.h"
87#include "nsCategoryManager.h"
88#include "nsICategoryManager.h"
89
90#include "nsAtomService.h"
91#include "nsAtomTable.h"
92#include "nsTraceRefcnt.h"
93
94#include "nsVariant.h"
95
96#include "SpecialSystemDirectory.h"
97
98#include "ipcdclient.h"
99#include "ipcService.h"
100#include "ipcConfig.h"
101#include "ipcCID.h"
102#include "ipcLockService.h"
103#include "ipcLockCID.h"
104#include "tmTransactionService.h"
105#include "ipcDConnectService.h"
106
107#include <locale.h>
108
109// Registry Factory creation function defined in nsRegistry.cpp
110// We hook into this function locally to create and register the registry
111// Since noone outside xpcom needs to know about this and nsRegistry.cpp
112// does not have a local include file, we are putting this definition
113// here rather than in nsIRegistry.h
114extern nsresult NS_RegistryGetFactory(nsIFactory** aFactory);
115extern nsresult NS_CategoryManagerGetFactory( nsIFactory** );
116
117static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
118static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
119
120NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsEventQueueServiceImpl, Init)
121
122#define NS_ENVIRONMENT_CLASSNAME "Environment Service"
123
124#include "nsXPCOM.h"
125// ds/nsISupportsPrimitives
126#define NS_SUPPORTS_ID_CLASSNAME "Supports ID"
127#define NS_SUPPORTS_CSTRING_CLASSNAME "Supports String"
128#define NS_SUPPORTS_STRING_CLASSNAME "Supports WString"
129#define NS_SUPPORTS_PRBOOL_CLASSNAME "Supports PRBool"
130#define NS_SUPPORTS_PRUINT8_CLASSNAME "Supports PRUint8"
131#define NS_SUPPORTS_PRUINT16_CLASSNAME "Supports PRUint16"
132#define NS_SUPPORTS_PRUINT32_CLASSNAME "Supports PRUint32"
133#define NS_SUPPORTS_PRUINT64_CLASSNAME "Supports PRUint64"
134#define NS_SUPPORTS_PRTIME_CLASSNAME "Supports PRTime"
135#define NS_SUPPORTS_CHAR_CLASSNAME "Supports Char"
136#define NS_SUPPORTS_PRINT16_CLASSNAME "Supports PRInt16"
137#define NS_SUPPORTS_PRINT32_CLASSNAME "Supports PRInt32"
138#define NS_SUPPORTS_PRINT64_CLASSNAME "Supports PRInt64"
139#define NS_SUPPORTS_FLOAT_CLASSNAME "Supports float"
140#define NS_SUPPORTS_DOUBLE_CLASSNAME "Supports double"
141#define NS_SUPPORTS_VOID_CLASSNAME "Supports void"
142#define NS_SUPPORTS_INTERFACE_POINTER_CLASSNAME "Supports interface pointer"
143
144NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsIDImpl)
145NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsStringImpl)
146NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsCStringImpl)
147NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRBoolImpl)
148NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint8Impl)
149NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint16Impl)
150NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint32Impl)
151NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRUint64Impl)
152NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRTimeImpl)
153NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsCharImpl)
154NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt16Impl)
155NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt32Impl)
156NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsPRInt64Impl)
157NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsFloatImpl)
158NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsDoubleImpl)
159NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsVoidImpl)
160NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsInterfacePointerImpl)
161
162NS_GENERIC_FACTORY_CONSTRUCTOR(nsArray)
163NS_GENERIC_FACTORY_CONSTRUCTOR(nsAtomService)
164NS_GENERIC_FACTORY_CONSTRUCTOR(nsExceptionService)
165NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryOutputStream)
166NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryInputStream)
167
168NS_GENERIC_FACTORY_CONSTRUCTOR(nsVariant)
169
170static NS_METHOD
171nsXPTIInterfaceInfoManagerGetSingleton(nsISupports* outer,
172 const nsIID& aIID,
173 void* *aInstancePtr)
174{
175 NS_ENSURE_ARG_POINTER(aInstancePtr);
176 NS_ENSURE_TRUE(!outer, NS_ERROR_NO_AGGREGATION);
177
178 nsCOMPtr<nsIInterfaceInfoManager> iim(dont_AddRef(XPTI_GetInterfaceInfoManager()));
179 if (!iim) {
180 return NS_ERROR_FAILURE;
181 }
182
183 return iim->QueryInterface(aIID, aInstancePtr);
184}
185
186
187PR_STATIC_CALLBACK(nsresult)
188RegisterGenericFactory(nsIComponentRegistrar* registrar,
189 const nsModuleComponentInfo *info)
190{
191 nsresult rv;
192 nsIGenericFactory* fact;
193 rv = NS_NewGenericFactory(&fact, info);
194 if (NS_FAILED(rv)) return rv;
195
196 rv = registrar->RegisterFactory(info->mCID,
197 info->mDescription,
198 info->mContractID,
199 fact);
200 NS_RELEASE(fact);
201 return rv;
202}
203
204// In order to support the installer, we need
205// to be told out of band if we should cause
206// an autoregister. If the file ".autoreg" exists in the binary
207// directory, we check its timestamp against the timestamp of the
208// compreg.dat file. If the .autoreg file is newer, we autoregister.
209static PRBool CheckUpdateFile()
210{
211 nsresult rv;
212 nsCOMPtr<nsIProperties> directoryService;
213 nsDirectoryService::Create(nsnull,
214 NS_GET_IID(nsIProperties),
215 getter_AddRefs(directoryService));
216
217 if (!directoryService)
218 return PR_FALSE;
219
220 nsCOMPtr<nsIFile> file;
221 rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
222 NS_GET_IID(nsIFile),
223 getter_AddRefs(file));
224
225 if (NS_FAILED(rv)) {
226 NS_WARNING("Getting NS_XPCOM_CURRENT_PROCESS_DIR failed");
227 return PR_FALSE;
228 }
229
230 file->AppendNative(nsDependentCString(".autoreg"));
231
232 PRBool exists;
233 file->Exists(&exists);
234 if (!exists)
235 return PR_FALSE;
236
237 nsCOMPtr<nsIFile> compregFile;
238 rv = directoryService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
239 NS_GET_IID(nsIFile),
240 getter_AddRefs(compregFile));
241
242
243 if (NS_FAILED(rv)) {
244 NS_WARNING("Getting NS_XPCOM_COMPONENT_REGISTRY_FILE failed");
245 return PR_FALSE;
246 }
247
248 // Don't need to check whether compreg exists; if it doesn't
249 // we won't even be here.
250
251 PRInt64 compregModTime, autoregModTime;
252 compregFile->GetLastModifiedTime(&compregModTime);
253 file->GetLastModifiedTime(&autoregModTime);
254
255 return LL_CMP(autoregModTime, >, compregModTime);
256}
257
258#if 0 /// @todo later
259NS_GENERIC_FACTORY_CONSTRUCTOR(ipcService)
260NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ipcLockService, Init)
261NS_GENERIC_FACTORY_CONSTRUCTOR(tmTransactionService)
262NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ipcDConnectService, Init)
263
264// enable this code to make the IPC DCONNECT service auto-start.
265NS_METHOD
266ipcDConnectServiceRegisterProc(nsIComponentManager *aCompMgr,
267 nsIFile *aPath,
268 const char *registryLocation,
269 const char *componentType,
270 const nsModuleComponentInfo *info)
271{
272 //
273 // add ipcService to the XPCOM startup category
274 //
275 nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
276 if (catman) {
277 nsXPIDLCString prevEntry;
278 catman->AddCategoryEntry(NS_XPCOM_STARTUP_OBSERVER_ID, "ipcDConnectService",
279 IPC_DCONNECTSERVICE_CONTRACTID, PR_TRUE, PR_TRUE,
280 getter_Copies(prevEntry));
281 }
282 return NS_OK;
283}
284
285NS_METHOD
286ipcDConnectServiceUnregisterProc(nsIComponentManager *aCompMgr,
287 nsIFile *aPath,
288 const char *registryLocation,
289 const nsModuleComponentInfo *info)
290{
291 nsCOMPtr<nsICategoryManager> catman(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
292 if (catman)
293 catman->DeleteCategoryEntry(NS_XPCOM_STARTUP_OBSERVER_ID,
294 IPC_DCONNECTSERVICE_CONTRACTID, PR_TRUE);
295 return NS_OK;
296}
297#endif
298
299nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = NULL;
300nsIProperties *gDirectoryService = NULL;
301PRBool gXPCOMShuttingDown = PR_FALSE;
302#ifdef VBOX
303static PRBool gXPCOMInitialized = PR_FALSE;
304#endif
305
306// For each class that wishes to support nsIClassInfo, add a line like this
307// NS_DECL_CLASSINFO(nsMyClass)
308
309#define COMPONENT(NAME, Ctor) \
310 { NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor }
311
312#define COMPONENT_CI(NAME, Ctor, Class) \
313 { NS_##NAME##_CLASSNAME, NS_##NAME##_CID, NS_##NAME##_CONTRACTID, Ctor, \
314 NULL, NULL, NULL, NS_CI_INTERFACE_GETTER_NAME(Class), NULL, \
315 &NS_CLASSINFO_NAME(Class) }
316
317static const nsModuleComponentInfo components[] = {
318 COMPONENT(DEBUG, nsDebugImpl::Create),
319#define NS_ERRORSERVICE_CLASSNAME NS_ERRORSERVICE_NAME
320 COMPONENT(ERRORSERVICE, nsErrorService::Create),
321
322 COMPONENT(SCRIPTABLEINPUTSTREAM, nsScriptableInputStream::Create),
323 COMPONENT(BINARYINPUTSTREAM, nsBinaryInputStreamConstructor),
324 COMPONENT(BINARYOUTPUTSTREAM, nsBinaryOutputStreamConstructor),
325
326#define NS_PROPERTIES_CLASSNAME "Properties"
327 COMPONENT(PROPERTIES, nsProperties::Create),
328
329 COMPONENT(SUPPORTSARRAY, nsSupportsArray::Create),
330 COMPONENT(ARRAY, nsArrayConstructor),
331 COMPONENT(EXCEPTIONSERVICE, nsExceptionServiceConstructor),
332 COMPONENT(ATOMSERVICE, nsAtomServiceConstructor),
333 COMPONENT(OBSERVERSERVICE, nsObserverService::Create),
334 COMPONENT(GENERICFACTORY, nsGenericFactory::Create),
335 COMPONENT(EVENTQUEUESERVICE, nsEventQueueServiceImplConstructor),
336 COMPONENT(EVENTQUEUE, nsEventQueueImpl::Create),
337 COMPONENT(THREAD, nsThread::Create),
338
339#define NS_XPCOMPROXY_CID NS_PROXYEVENT_MANAGER_CID
340 COMPONENT(XPCOMPROXY, nsProxyObjectManager::Create),
341
342#define COMPONENT_SUPPORTS(TYPE, Type) \
343 COMPONENT(SUPPORTS_##TYPE, nsSupports##Type##ImplConstructor)
344
345 COMPONENT_SUPPORTS(ID, ID),
346 COMPONENT_SUPPORTS(STRING, String),
347 COMPONENT_SUPPORTS(CSTRING, CString),
348 COMPONENT_SUPPORTS(PRBOOL, PRBool),
349 COMPONENT_SUPPORTS(PRUINT8, PRUint8),
350 COMPONENT_SUPPORTS(PRUINT16, PRUint16),
351 COMPONENT_SUPPORTS(PRUINT32, PRUint32),
352 COMPONENT_SUPPORTS(PRUINT64, PRUint64),
353 COMPONENT_SUPPORTS(PRTIME, PRTime),
354 COMPONENT_SUPPORTS(CHAR, Char),
355 COMPONENT_SUPPORTS(PRINT16, PRInt16),
356 COMPONENT_SUPPORTS(PRINT32, PRInt32),
357 COMPONENT_SUPPORTS(PRINT64, PRInt64),
358 COMPONENT_SUPPORTS(FLOAT, Float),
359 COMPONENT_SUPPORTS(DOUBLE, Double),
360 COMPONENT_SUPPORTS(VOID, Void),
361 COMPONENT_SUPPORTS(INTERFACE_POINTER, InterfacePointer),
362
363#undef COMPONENT_SUPPORTS
364#define NS_LOCAL_FILE_CLASSNAME "Local File Specification"
365 COMPONENT(LOCAL_FILE, nsLocalFile::nsLocalFileConstructor),
366#define NS_DIRECTORY_SERVICE_CLASSNAME "nsIFile Directory Service"
367 COMPONENT(DIRECTORY_SERVICE, nsDirectoryService::Create),
368
369 COMPONENT(VARIANT, nsVariantConstructor),
370 COMPONENT(INTERFACEINFOMANAGER_SERVICE, nsXPTIInterfaceInfoManagerGetSingleton),
371
372#if 0 /// @todo later
373 { IPC_SERVICE_CLASSNAME,
374 IPC_SERVICE_CID,
375 IPC_SERVICE_CONTRACTID,
376 ipcServiceConstructor },
377 /*
378 ipcServiceRegisterProc,
379 ipcServiceUnregisterProc },
380 */
381 //
382 // extensions go here:
383 //
384 { IPC_LOCKSERVICE_CLASSNAME,
385 IPC_LOCKSERVICE_CID,
386 IPC_LOCKSERVICE_CONTRACTID,
387 ipcLockServiceConstructor },
388 { IPC_TRANSACTIONSERVICE_CLASSNAME,
389 IPC_TRANSACTIONSERVICE_CID,
390 IPC_TRANSACTIONSERVICE_CONTRACTID,
391 tmTransactionServiceConstructor },
392
393#ifdef BUILD_DCONNECT
394 { IPC_DCONNECTSERVICE_CLASSNAME,
395 IPC_DCONNECTSERVICE_CID,
396 IPC_DCONNECTSERVICE_CONTRACTID,
397 ipcDConnectServiceConstructor,
398 ipcDConnectServiceRegisterProc,
399 ipcDConnectServiceUnregisterProc },
400#endif
401#endif
402};
403
404#undef COMPONENT
405
406const int components_length = sizeof(components) / sizeof(components[0]);
407
408// gDebug will be freed during shutdown.
409static nsIDebug* gDebug = nsnull;
410nsresult NS_COM NS_GetDebug(nsIDebug** result)
411{
412 nsresult rv = NS_OK;
413 if (!gDebug)
414 {
415 rv = nsDebugImpl::Create(nsnull,
416 NS_GET_IID(nsIDebug),
417 (void**)&gDebug);
418 }
419 NS_IF_ADDREF(*result = gDebug);
420 return rv;
421}
422
423#ifdef NS_BUILD_REFCNT_LOGGING
424// gTraceRefcnt will be freed during shutdown.
425static nsITraceRefcnt* gTraceRefcnt = nsnull;
426#endif
427
428nsresult NS_COM NS_GetTraceRefcnt(nsITraceRefcnt** result)
429{
430#ifdef NS_BUILD_REFCNT_LOGGING
431 nsresult rv = NS_OK;
432 if (!gTraceRefcnt)
433 {
434 rv = nsTraceRefcntImpl::Create(nsnull,
435 NS_GET_IID(nsITraceRefcnt),
436 (void**)&gTraceRefcnt);
437 }
438 NS_IF_ADDREF(*result = gTraceRefcnt);
439 return rv;
440#else
441 return NS_ERROR_NOT_INITIALIZED;
442#endif
443}
444
445#ifdef VBOX
446PRBool NS_COM NS_IsXPCOMInitialized(void)
447{
448 return gXPCOMInitialized;
449}
450#endif
451
452nsresult NS_COM NS_InitXPCOM(nsIServiceManager* *result,
453 nsIFile* binDirectory)
454{
455 return NS_InitXPCOM2(result, binDirectory, nsnull);
456}
457
458nsresult NS_COM NS_InitXPCOM2(nsIServiceManager* *result,
459 nsIFile* binDirectory,
460 nsIDirectoryServiceProvider* appFileLocationProvider)
461{
462 nsresult rv = NS_OK;
463
464 // We are not shutting down
465 gXPCOMShuttingDown = PR_FALSE;
466
467#ifdef NS_BUILD_REFCNT_LOGGING
468 nsTraceRefcntImpl::Startup();
469#endif
470
471 // Establish the main thread here.
472 rv = nsIThread::SetMainThread();
473 if (NS_FAILED(rv)) return rv;
474
475 // If the locale hasn't already been setup by our embedder,
476 // get us out of the "C" locale and into the system
477 if (strcmp(setlocale(LC_ALL, NULL), "C") == 0)
478 setlocale(LC_ALL, "");
479
480#if defined(XP_UNIX) || defined(XP_OS2)
481 NS_StartupNativeCharsetUtils();
482#endif
483 NS_StartupLocalFile();
484
485 StartupSpecialSystemDirectory();
486
487 // Start the directory service so that the component manager init can use it.
488 rv = nsDirectoryService::Create(nsnull,
489 NS_GET_IID(nsIProperties),
490 (void**)&gDirectoryService);
491 if (NS_FAILED(rv))
492 return rv;
493
494 nsCOMPtr<nsIDirectoryService> dirService = do_QueryInterface(gDirectoryService, &rv);
495 if (NS_FAILED(rv))
496 return rv;
497 rv = dirService->Init();
498 if (NS_FAILED(rv))
499 return rv;
500
501 // Create the Component/Service Manager
502 nsComponentManagerImpl *compMgr = NULL;
503
504 if (nsComponentManagerImpl::gComponentManager == NULL)
505 {
506 compMgr = new nsComponentManagerImpl();
507 if (compMgr == NULL)
508 return NS_ERROR_OUT_OF_MEMORY;
509 NS_ADDREF(compMgr);
510
511 nsCOMPtr<nsIFile> xpcomLib;
512
513 PRBool value;
514 if (binDirectory)
515 {
516 rv = binDirectory->IsDirectory(&value);
517
518 if (NS_SUCCEEDED(rv) && value) {
519 gDirectoryService->Set(NS_XPCOM_INIT_CURRENT_PROCESS_DIR, binDirectory);
520 binDirectory->Clone(getter_AddRefs(xpcomLib));
521 }
522 }
523 else {
524 gDirectoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
525 NS_GET_IID(nsIFile),
526 getter_AddRefs(xpcomLib));
527 }
528
529 if (xpcomLib) {
530 xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL));
531 gDirectoryService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
532 }
533
534 if (appFileLocationProvider) {
535 rv = dirService->RegisterProvider(appFileLocationProvider);
536 if (NS_FAILED(rv)) return rv;
537 }
538
539 rv = compMgr->Init();
540 if (NS_FAILED(rv))
541 {
542 NS_RELEASE(compMgr);
543 return rv;
544 }
545
546 nsComponentManagerImpl::gComponentManager = compMgr;
547
548 if (result) {
549 nsIServiceManager *serviceManager =
550 NS_STATIC_CAST(nsIServiceManager*, compMgr);
551
552 NS_ADDREF(*result = serviceManager);
553 }
554 }
555
556 rv = compMgr->RegisterService(kComponentManagerCID, NS_STATIC_CAST(nsIComponentManager*, compMgr));
557 if (NS_FAILED(rv)) return rv;
558
559 // 2. Register the global services with the component manager so that
560 // clients can create new objects.
561
562 // Category Manager
563 {
564 nsCOMPtr<nsIFactory> categoryManagerFactory;
565 if ( NS_FAILED(rv = NS_CategoryManagerGetFactory(getter_AddRefs(categoryManagerFactory))) )
566 return rv;
567
568 NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
569
570 rv = compMgr->RegisterFactory(kCategoryManagerCID,
571 NS_CATEGORYMANAGER_CLASSNAME,
572 NS_CATEGORYMANAGER_CONTRACTID,
573 categoryManagerFactory,
574 PR_TRUE);
575 if ( NS_FAILED(rv) ) return rv;
576 }
577
578 // what I want to do here is QI for a Component Registration Manager. Since this
579 // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
580 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(
581 NS_STATIC_CAST(nsIComponentManager*,compMgr), &rv);
582 if (registrar) {
583 for (int i = 0; i < components_length; i++)
584 RegisterGenericFactory(registrar, &components[i]);
585 }
586 rv = nsComponentManagerImpl::gComponentManager->ReadPersistentRegistry();
587#ifdef DEBUG
588 if (NS_FAILED(rv)) {
589 printf("No Persistent Registry Found.\n");
590 }
591#endif
592
593#if 0 /// @todo later
594 rv = IPC_Init();
595 if (NS_FAILED(rv))
596 return rv;
597#endif
598
599 if ( NS_FAILED(rv) || CheckUpdateFile()) {
600 // if we find no persistent registry, we will try to autoregister
601 // the default components directory.
602 nsComponentManagerImpl::gComponentManager->AutoRegister(nsnull);
603
604 // If the application is using a GRE, then,
605 // auto register components in the GRE directory as well.
606 //
607 // The application indicates that it's using an GRE by
608 // returning a valid nsIFile when queried (via appFileLocProvider)
609 // for the NS_GRE_DIR atom as shown below
610 //
611
612 if ( appFileLocationProvider ) {
613 nsCOMPtr<nsIFile> greDir;
614 PRBool persistent = PR_TRUE;
615
616 appFileLocationProvider->GetFile(NS_GRE_DIR, &persistent, getter_AddRefs(greDir));
617
618 if (greDir) {
619#ifdef DEBUG_dougt
620 printf("start - Registering GRE components\n");
621#endif
622 rv = gDirectoryService->Get(NS_GRE_COMPONENT_DIR,
623 NS_GET_IID(nsIFile),
624 getter_AddRefs(greDir));
625 if (NS_FAILED(rv)) {
626 NS_ERROR("Could not get GRE components directory!");
627 return rv;
628 }
629
630 // If the GRE contains any loaders, we want to know about it so that we can cause another
631 // autoregistration of the applications component directory.
632 int loaderCount = nsComponentManagerImpl::gComponentManager->GetLoaderCount();
633 rv = nsComponentManagerImpl::gComponentManager->AutoRegister(greDir);
634
635 if (loaderCount != nsComponentManagerImpl::gComponentManager->GetLoaderCount())
636 nsComponentManagerImpl::gComponentManager->AutoRegisterNonNativeComponents(nsnull);
637
638#ifdef DEBUG_dougt
639 printf("end - Registering GRE components\n");
640#endif
641 if (NS_FAILED(rv)) {
642 NS_ERROR("Could not AutoRegister GRE components");
643 return rv;
644 }
645 }
646 }
647
648 //
649 // If additional component directories have been specified, then
650 // register them as well.
651 //
652
653 nsCOMPtr<nsISimpleEnumerator> dirList;
654 gDirectoryService->Get(NS_XPCOM_COMPONENT_DIR_LIST,
655 NS_GET_IID(nsISimpleEnumerator),
656 getter_AddRefs(dirList));
657 if (dirList) {
658 PRBool hasMore;
659 while (NS_SUCCEEDED(dirList->HasMoreElements(&hasMore)) && hasMore) {
660 nsCOMPtr<nsISupports> elem;
661 dirList->GetNext(getter_AddRefs(elem));
662 if (elem) {
663 nsCOMPtr<nsIFile> dir = do_QueryInterface(elem);
664 if (dir)
665 nsComponentManagerImpl::gComponentManager->AutoRegister(dir);
666
667 // XXX should we worry about new component loaders being
668 // XXX defined by this process?
669 }
670 }
671 }
672
673
674 // Make sure the compreg file's mod time is current.
675 nsCOMPtr<nsIFile> compregFile;
676 rv = gDirectoryService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
677 NS_GET_IID(nsIFile),
678 getter_AddRefs(compregFile));
679 compregFile->SetLastModifiedTime(PR_Now() / 1000);
680 }
681
682 // Pay the cost at startup time of starting this singleton.
683 nsIInterfaceInfoManager* iim = XPTI_GetInterfaceInfoManager();
684 NS_IF_RELEASE(iim);
685#ifdef VBOX
686 // Must initialize the EventQueueService singleton before anyone is
687 // using it. The notification below creates a thread which races creating
688 // the EventQueueService creation otherwise, no matter what.
689 nsCOMPtr<nsIEventQueue> eventQ;
690 rv = NS_GetMainEventQ(getter_AddRefs(eventQ));
691 if (NS_FAILED(rv)) {
692 NS_ERROR("Could not create event queue for main thread");
693 /* this is just a build-time hack, to reference NS_ProxyRelease */
694 if (rv == 666)
695 NS_ProxyRelease(nsnull, nsnull);
696 return rv;
697 }
698#endif /* VBOX */
699
700 // Notify observers of xpcom autoregistration start
701 NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_OBSERVER_ID,
702 nsnull,
703 NS_XPCOM_STARTUP_OBSERVER_ID);
704
705#ifdef VBOX
706 gXPCOMInitialized = PR_TRUE;
707#endif
708 return NS_OK;
709}
710
711
712static nsVoidArray* gExitRoutines;
713
714static void CallExitRoutines()
715{
716 if (!gExitRoutines)
717 return;
718
719 PRInt32 count = gExitRoutines->Count();
720 for (PRInt32 i = 0; i < count; i++) {
721 XPCOMExitRoutine func = (XPCOMExitRoutine) gExitRoutines->ElementAt(i);
722 func();
723 }
724 gExitRoutines->Clear();
725 delete gExitRoutines;
726 gExitRoutines = nsnull;
727}
728
729nsresult NS_COM
730NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, PRUint32 priority)
731{
732 // priority are not used right now. It will need to be implemented as more
733 // classes are moved into the glue library --dougt
734 if (!gExitRoutines) {
735 gExitRoutines = new nsVoidArray();
736 if (!gExitRoutines) {
737 NS_WARNING("Failed to allocate gExitRoutines");
738 return NS_ERROR_FAILURE;
739 }
740 }
741
742 PRBool okay = gExitRoutines->AppendElement((void*)exitRoutine);
743 return okay ? NS_OK : NS_ERROR_FAILURE;
744}
745
746nsresult NS_COM
747NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine)
748{
749 if (!gExitRoutines)
750 return NS_ERROR_FAILURE;
751
752 PRBool okay = gExitRoutines->RemoveElement((void*)exitRoutine);
753 return okay ? NS_OK : NS_ERROR_FAILURE;
754}
755
756
757//
758// NS_ShutdownXPCOM()
759//
760// The shutdown sequence for xpcom would be
761//
762// - Release the Global Service Manager
763// - Release all service instances held by the global service manager
764// - Release the Global Service Manager itself
765// - Release the Component Manager
766// - Release all factories cached by the Component Manager
767// - Unload Libraries
768// - Release Contractid Cache held by Component Manager
769// - Release dll abstraction held by Component Manager
770// - Release the Registry held by Component Manager
771// - Finally, release the component manager itself
772//
773nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
774{
775
776 // Notify observers of xpcom shutting down
777 nsresult rv = NS_OK;
778 {
779 // Block it so that the COMPtr will get deleted before we hit
780 // servicemanager shutdown
781 nsCOMPtr<nsIObserverService> observerService =
782 do_GetService("@mozilla.org/observer-service;1", &rv);
783 if (NS_SUCCEEDED(rv))
784 {
785 nsCOMPtr<nsIServiceManager> mgr;
786 rv = NS_GetServiceManager(getter_AddRefs(mgr));
787 if (NS_SUCCEEDED(rv))
788 {
789 (void) observerService->NotifyObservers(mgr,
790 NS_XPCOM_SHUTDOWN_OBSERVER_ID,
791 nsnull);
792 }
793 }
794 }
795
796 // grab the event queue so that we can process events one last time before exiting
797 nsCOMPtr <nsIEventQueue> currentQ;
798 {
799 nsCOMPtr<nsIEventQueueService> eventQService =
800 do_GetService(kEventQueueServiceCID, &rv);
801
802 if (eventQService) {
803 eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(currentQ));
804 }
805 }
806 // XPCOM is officially in shutdown mode NOW
807 // Set this only after the observers have been notified as this
808 // will cause servicemanager to become inaccessible.
809 gXPCOMShuttingDown = PR_TRUE;
810
811#ifdef DEBUG_dougt
812 fprintf(stderr, "* * * * XPCOM shutdown. Access will be denied * * * * \n");
813#endif
814
815#if 0 /// @todo later
816 IPC_Shutdown();
817#endif
818
819 // We may have AddRef'd for the caller of NS_InitXPCOM, so release it
820 // here again:
821 NS_IF_RELEASE(servMgr);
822
823 // Shutdown global servicemanager
824 if (nsComponentManagerImpl::gComponentManager) {
825 nsComponentManagerImpl::gComponentManager->FreeServices();
826 }
827 nsServiceManager::ShutdownGlobalServiceManager(nsnull);
828
829 if (currentQ) {
830 currentQ->ProcessPendingEvents();
831 currentQ = 0;
832 }
833
834 nsProxyObjectManager::Shutdown();
835
836 // Release the directory service
837 NS_IF_RELEASE(gDirectoryService);
838
839 // Shutdown nsLocalFile string conversion
840 NS_ShutdownLocalFile();
841#ifdef XP_UNIX
842 NS_ShutdownNativeCharsetUtils();
843#endif
844
845 CallExitRoutines();
846
847 // Shutdown xpcom. This will release all loaders and cause others holding
848 // a refcount to the component manager to release it.
849 if (nsComponentManagerImpl::gComponentManager) {
850 rv = (nsComponentManagerImpl::gComponentManager)->Shutdown();
851 NS_ASSERTION(NS_SUCCEEDED(rv), "Component Manager shutdown failed.");
852 } else
853 NS_WARNING("Component Manager was never created ...");
854
855 // Release our own singletons
856 // Do this _after_ shutting down the component manager, because the
857 // JS component loader will use XPConnect to call nsIModule::canUnload,
858 // and that will spin up the InterfaceInfoManager again -- bad mojo
859 XPTI_FreeInterfaceInfoManager();
860
861 // Finally, release the component manager last because it unloads the
862 // libraries:
863 if (nsComponentManagerImpl::gComponentManager) {
864 nsrefcnt cnt;
865 NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt);
866 NS_WARN_IF_FALSE(cnt == 0, "Component Manager being held past XPCOM shutdown.");
867 }
868 nsComponentManagerImpl::gComponentManager = nsnull;
869
870 ShutdownSpecialSystemDirectory();
871
872 EmptyEnumeratorImpl::Shutdown();
873
874 nsThread::Shutdown();
875 NS_PurgeAtomTable();
876
877 NS_IF_RELEASE(gDebug);
878
879#ifdef NS_BUILD_REFCNT_LOGGING
880 nsTraceRefcntImpl::DumpStatistics();
881 nsTraceRefcntImpl::ResetStatistics();
882 nsTraceRefcntImpl::Shutdown();
883#endif
884
885#ifdef VBOX
886 gXPCOMInitialized = PR_FALSE;
887#endif
888 return NS_OK;
889}
890
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette