VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/components/nsNativeComponentLoader.cpp@ 102204

最後變更 在這個檔案從102204是 102204,由 vboxsync 提交於 14 月 前

libs/xpcom/xpcom: Get rid of last PR_GetErrorText() usages which are not relevant anyway, bguref:10545

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 29.1 KB
 
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) 1999
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 * This Original Code has been modified by IBM Corporation.
38 * Modifications made by IBM described herein are
39 * Copyright (c) International Business Machines
40 * Corporation, 2000
41 *
42 * Modifications to Mozilla code or documentation
43 * identified per MPL Section 3.3
44 *
45 * Date Modified by Description of modification
46 * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
47 */
48
49#include "prmem.h"
50#include "nsNativeComponentLoader.h"
51#include "nsComponentManager.h"
52#include "nsCOMPtr.h"
53#include "nsIServiceManager.h"
54#include "nsIModule.h"
55#include "xcDll.h"
56#include "nsHashtable.h"
57#include "nsXPIDLString.h"
58#include "nsCRT.h"
59#include "nsIObserverService.h"
60
61#include <iprt/assert.h>
62#include <VBox/log.h>
63
64static PRBool PR_CALLBACK
65DLLStore_Destroy(nsHashKey *aKey, void *aData, void* closure)
66{
67 nsDll* entry = NS_STATIC_CAST(nsDll*, aData);
68 delete entry;
69 return PR_TRUE;
70}
71
72nsNativeComponentLoader::nsNativeComponentLoader() :
73 mCompMgr(nsnull),
74 mLoadedDependentLibs(16, PR_TRUE),
75 mDllStore(nsnull, nsnull, DLLStore_Destroy,
76 nsnull, 256, PR_TRUE)
77{
78}
79
80NS_IMPL_THREADSAFE_ISUPPORTS2(nsNativeComponentLoader,
81 nsIComponentLoader,
82 nsINativeComponentLoader)
83
84NS_IMETHODIMP
85nsNativeComponentLoader::GetFactory(const nsIID & aCID,
86 const char *aLocation,
87 const char *aType,
88 nsIFactory **_retval)
89{
90 nsresult rv;
91
92 if (!_retval)
93 return NS_ERROR_NULL_POINTER;
94
95 /* use a hashtable of WeakRefs to store the factory object? */
96
97 /* Should this all live in xcDll? */
98 nsDll *dll;
99 rv = CreateDll(nsnull, aLocation, &dll);
100 if (NS_FAILED(rv))
101 return rv;
102
103 if (!dll)
104 return NS_ERROR_OUT_OF_MEMORY;
105
106 if (!dll->IsLoaded()) {
107#ifdef LOG_ENABLED
108 nsXPIDLCString displayPath;
109 dll->GetDisplayPath(displayPath);
110
111 Log(("nsNativeComponentLoader: loading \"%s\"\n", displayPath.get()));
112#endif
113 if (!dll->Load()) {
114
115 Log(("nsNativeComponentLoader: load FAILED\n"));
116
117 /** @todo r=aeichner Get error information from RTLdr. */
118 char errorMsg[1024] = "<unknown; can't get error from NSPR>";
119 DumpLoadError(dll, "GetFactory", errorMsg);
120 return NS_ERROR_FAILURE;
121 }
122 }
123
124 /* Get service manager for factory */
125 nsCOMPtr<nsIServiceManager> serviceMgr;
126 rv = NS_GetServiceManager(getter_AddRefs(serviceMgr));
127 if (NS_FAILED(rv))
128 return rv; // XXX translate error code?
129
130 rv = GetFactoryFromModule(dll, aCID, _retval);
131
132 Log(("nsNativeComponentLoader: Factory creation %s for %s",
133 (NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"),
134 aLocation));
135
136 // If the dll failed to get us a factory. But the dll registered that
137 // it would be able to create a factory for this CID. mmh!
138 // We cannot just delete the dll as the dll could be hosting
139 // other CID for which factory creation can pass.
140 // We will just let it be. The effect will be next time we try
141 // creating the object, we will query the dll again. Since the
142 // dll is loaded, this aint a big hit. So for optimized builds
143 // this is ok to limp along.
144 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Factory creation failed");
145
146 return rv;
147}
148
149NS_IMETHODIMP
150nsNativeComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aReg)
151{
152 mCompMgr = aCompMgr;
153 if (!mCompMgr)
154 return NS_ERROR_INVALID_ARG;
155
156 return NS_OK;
157}
158
159NS_IMETHODIMP
160nsNativeComponentLoader::AutoRegisterComponents(PRInt32 aWhen,
161 nsIFile *aDirectory)
162{
163 Log(("nsNativeComponentLoader: autoregistering begins.\n"));
164
165 nsresult rv = RegisterComponentsInDir(aWhen, aDirectory);
166
167 Log(("nsNativeComponentLoader: autoregistering %s\n",
168 NS_FAILED(rv) ? "FAILED" : "succeeded"));
169 return rv;
170}
171
172nsresult
173nsNativeComponentLoader::RegisterComponentsInDir(PRInt32 when,
174 nsIFile *dir)
175{
176 nsresult rv = NS_ERROR_FAILURE;
177 PRBool isDir = PR_FALSE;
178
179 // Create a directory iterator
180 nsCOMPtr<nsISimpleEnumerator> dirIterator;
181 rv = dir->GetDirectoryEntries(getter_AddRefs(dirIterator));
182
183 if (NS_FAILED(rv)) return rv;
184
185 // whip through the directory to register every file
186 nsCOMPtr<nsIFile> dirEntry;
187 PRBool more = PR_FALSE;
188
189 rv = dirIterator->HasMoreElements(&more);
190 if (NS_FAILED(rv)) return rv;
191 while (more == PR_TRUE)
192 {
193 rv = dirIterator->GetNext((nsISupports**)getter_AddRefs(dirEntry));
194 if (NS_SUCCEEDED(rv))
195 {
196 rv = dirEntry->IsDirectory(&isDir);
197 if (NS_SUCCEEDED(rv))
198 {
199 if (isDir == PR_TRUE)
200 {
201 // This is a directory. Grovel for components into the directory.
202#ifdef RT_OS_DARWIN // But not if it's a debug bundle.
203 nsCAutoString leafName;
204 rv = dirEntry->GetNativeLeafName(leafName);
205 if ( NS_FAILED(rv)
206 || leafName.Length() < sizeof(".dSYM")
207 || PL_strcasecmp(leafName.get() + (leafName.Length() - sizeof(".dSYM") + 1), ".dSYM"))
208#endif
209 rv = RegisterComponentsInDir(when, dirEntry);
210 }
211 else
212 {
213 PRBool registered;
214 // This is a file. Try to register it.
215 rv = AutoRegisterComponent(when, dirEntry, &registered);
216 }
217 }
218 }
219 rv = dirIterator->HasMoreElements(&more);
220 if (NS_FAILED(rv)) return rv;
221 }
222
223 return rv;
224}
225
226DECLINLINE(void) nsLogDllMsg(nsDll *dll, const char *pszWhat)
227{
228#ifdef LOG_ENABLED
229 nsXPIDLCString displayPath;
230 dll->GetDisplayPath(displayPath);
231
232 Log(("nsNativeComponentLoader: %s \"%s\".\n", pszWhat, displayPath.get()));
233#endif
234}
235
236static nsresult PR_CALLBACK
237nsFreeLibrary(nsDll *dll, nsIServiceManager *serviceMgr, PRInt32 when)
238{
239 nsresult rv = NS_ERROR_FAILURE;
240
241 if (!dll || dll->IsLoaded() == PR_FALSE)
242 {
243 return NS_ERROR_INVALID_ARG;
244 }
245
246 // Get if the dll was marked for unload in an earlier round
247 PRBool dllMarkedForUnload = dll->IsMarkedForUnload();
248
249 // Reset dll marking for unload just in case we return with
250 // an error.
251 dll->MarkForUnload(PR_FALSE);
252
253 PRBool canUnload = PR_FALSE;
254
255 // Get the module object
256 nsCOMPtr<nsIModule> mobj;
257 /* XXXshaver cheat and use the global component manager */
258 rv = dll->GetModule(NS_STATIC_CAST(nsIComponentManager*, nsComponentManagerImpl::gComponentManager),
259 getter_AddRefs(mobj));
260 if (NS_SUCCEEDED(rv))
261 {
262 rv = mobj->CanUnload(nsComponentManagerImpl::gComponentManager, &canUnload);
263 }
264
265 mobj = nsnull; // Release our reference to the module object
266 // When shutting down, whether we can unload the dll or not,
267 // we will shutdown the dll to release any memory it has got
268 if (when == nsIComponentManagerObsolete::NS_Shutdown)
269 {
270 dll->Shutdown();
271 }
272
273 // Check error status on CanUnload() call
274 if (NS_FAILED(rv))
275 {
276 nsLogDllMsg(dll, "nsIModule::CanUnload() returned error for");
277 return rv;
278 }
279
280 if (canUnload)
281 {
282 if (dllMarkedForUnload)
283 {
284 nsLogDllMsg(dll, "+ Unloading");
285
286#ifdef DEBUG_dougt
287 // XXX dlls aren't counting their outstanding instances correctly
288 // XXX hence, dont unload until this gets enforced.
289 rv = dll->Unload();
290#endif /* 0 */
291 }
292 else
293 nsLogDllMsg(dll, "Ready for unload");
294 }
295 else
296 {
297 nsLogDllMsg(dll, "NOT ready for unload");
298 rv = NS_ERROR_FAILURE;
299 }
300 return rv;
301}
302
303struct freeLibrariesClosure
304{
305 nsIServiceManager *serviceMgr;
306 PRInt32 when;
307};
308
309static PRBool PR_CALLBACK
310nsFreeLibraryEnum(nsHashKey *aKey, void *aData, void* closure)
311{
312 nsDll *dll = (nsDll *) aData;
313 struct freeLibrariesClosure *callData = (struct freeLibrariesClosure *) closure;
314 nsFreeLibrary(dll,
315 (callData ? callData->serviceMgr : NULL),
316 (callData ? callData->when : nsIComponentManagerObsolete::NS_Timer));
317 return PR_TRUE;
318}
319
320/*
321 * SelfRegisterDll
322 *
323 * Given a dll abstraction, this will load, selfregister the dll and
324 * unload the dll.
325 *
326 */
327nsresult
328nsNativeComponentLoader::SelfRegisterDll(nsDll *dll,
329 const char *registryLocation,
330 PRBool deferred)
331{
332 // Precondition: dll is not loaded already, unless we're deferred
333 Assert(deferred || dll->IsLoaded() == PR_FALSE);
334
335 nsresult res;
336 nsCOMPtr<nsIServiceManager> serviceMgr;
337 res = NS_GetServiceManager(getter_AddRefs(serviceMgr));
338 if (NS_FAILED(res)) return res;
339
340 if (dll->Load() == PR_FALSE)
341 {
342 /** @todo r=aeichner Get error text from RTLdr(). */
343 // Cannot load. Probably not a dll.
344 char errorMsg[1024] = "Cannot get error from nspr. Not enough memory.";
345 DumpLoadError(dll, "SelfRegisterDll", errorMsg);
346 return NS_ERROR_FAILURE;
347 }
348
349 nsLogDllMsg(dll, "Loaded");
350
351 // Tell the module to self register
352 nsCOMPtr<nsIFile> fs;
353 nsCOMPtr<nsIModule> mobj;
354 res = dll->GetModule(mCompMgr, getter_AddRefs(mobj));
355 if (NS_SUCCEEDED(res))
356 {
357 /*************************************************************
358 * WARNING: Why are use introducing 'res2' here and then *
359 * later assigning it to 'res' rather than just using 'res'? *
360 * This is because this code turns up a code-generation bug *
361 * in VC6 on NT. Assigning to 'res' on the next line causes *
362 * the value of 'dll' to get nulled out! The two seem to be *
363 * getting aliased together during compilation. *
364 *************************************************************/
365 nsresult res2 = dll->GetDllSpec(getter_AddRefs(fs)); // don't change 'res2' -- see warning, above
366 if (NS_SUCCEEDED(res2)) {
367 // in the case of re-registering a component, we want to remove
368 // any optional data that this file may have had.
369 AddDependentLibrary(fs, nsnull);
370
371 res = mobj->RegisterSelf(mCompMgr, fs, registryLocation,
372 nativeComponentType);
373 }
374 else
375 {
376 res = res2; // don't take this out -- see warning, above
377 nsLogDllMsg(dll, "dll->GetDllSpec() FAILED on");
378 }
379 mobj = NULL; // Force a release of the Module object before unload()
380 }
381
382 // Update the timestamp and size of the dll in registry
383 // Don't enter deferred modules in the registry, because it might only be
384 // able to register on some later autoreg, after another component has been
385 // installed.
386 if (res != NS_ERROR_FACTORY_REGISTER_AGAIN) {
387 PRInt64 modTime;
388 if (!fs)
389 return res;
390
391 fs->GetLastModifiedTime(&modTime);
392 nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(mCompMgr);
393 if (!manager)
394 return NS_ERROR_FAILURE;
395
396 nsCOMPtr<nsIFile> fs;
397 res = dll->GetDllSpec(getter_AddRefs(fs));
398 if (NS_FAILED(res)) return res;
399
400 manager->SaveFileInfo(fs, registryLocation, modTime);
401 }
402
403 return res;
404}
405
406nsresult
407nsNativeComponentLoader::DumpLoadError(nsDll *dll,
408 const char *aCallerName,
409 const char *aNsprErrorMsg)
410{
411 Assert(aCallerName != NULL);
412
413 if (nsnull == dll || nsnull == aNsprErrorMsg)
414 return NS_OK;
415
416 nsCAutoString errorMsg(aNsprErrorMsg);
417
418 nsXPIDLCString displayPath;
419 dll->GetDisplayPath(displayPath);
420
421#ifdef DEBUG
422 fprintf(stderr,
423 "nsNativeComponentLoader: %s(%s) Load FAILED with error: %s\n",
424 aCallerName,
425 displayPath.get(),
426 errorMsg.get());
427#endif
428
429 Log(("nsNativeComponentLoader: %s(%s) Load FAILED with error: %s",
430 aCallerName, displayPath.get(), errorMsg.get()));
431 return NS_OK;
432}
433
434nsresult
435nsNativeComponentLoader::SelfUnregisterDll(nsDll *dll)
436{
437 nsresult res;
438 nsCOMPtr<nsIServiceManager> serviceMgr;
439 res = NS_GetServiceManager(getter_AddRefs(serviceMgr));
440 if (NS_FAILED(res)) return res;
441
442 if (dll->Load() == PR_FALSE)
443 {
444 // Cannot load. Probably not a dll.
445 return(NS_ERROR_FAILURE);
446 }
447
448 // Tell the module to self register
449 nsCOMPtr<nsIModule> mobj;
450 res = dll->GetModule(mCompMgr, getter_AddRefs(mobj));
451 if (NS_SUCCEEDED(res))
452 {
453 nsLogDllMsg(dll, "using nsIModule to unregister self on");
454
455 nsCOMPtr<nsIFile> fs;
456 res = dll->GetDllSpec(getter_AddRefs(fs));
457 if (NS_FAILED(res)) return res;
458 // Get registry location for spec
459 nsXPIDLCString registryName;
460
461 // what I want to do here is QI for a Component Registration Manager. Since this
462 // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
463 nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &res);
464 if (obsoleteManager)
465 res = obsoleteManager->RegistryLocationForSpec(fs, getter_Copies(registryName));
466
467 if (NS_FAILED(res)) return res;
468 mobj->UnregisterSelf(mCompMgr, fs, registryName);
469 }
470 return res;
471}
472
473nsresult
474nsNativeComponentLoader::AutoUnregisterComponent(PRInt32 when,
475 nsIFile *component,
476 PRBool *unregistered)
477{
478
479 nsresult rv = NS_ERROR_FAILURE;
480
481 *unregistered = PR_FALSE;
482
483 nsXPIDLCString persistentDescriptor;
484 // what I want to do here is QI for a Component Registration Manager. Since this
485 // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
486 nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
487 if (obsoleteManager)
488 rv = obsoleteManager->RegistryLocationForSpec(component,
489 getter_Copies(persistentDescriptor));
490 if (NS_FAILED(rv)) return rv;
491
492 // Notify observers, if any, of autoregistration work
493 nsCOMPtr<nsIObserverService> observerService =
494 do_GetService("@mozilla.org/observer-service;1", &rv);
495 if (NS_SUCCEEDED(rv))
496 {
497 nsCOMPtr<nsIServiceManager> mgr;
498 rv = NS_GetServiceManager(getter_AddRefs(mgr));
499 if (NS_SUCCEEDED(rv))
500 {
501 (void) observerService->NotifyObservers(mgr,
502 NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
503 NS_LITERAL_STRING("Unregistering native component").get());
504 }
505 }
506
507 nsDll *dll = NULL;
508 rv = CreateDll(component, persistentDescriptor, &dll);
509 if (NS_FAILED(rv) || dll == NULL) return rv;
510
511 rv = SelfUnregisterDll(dll);
512
513 if (NS_SUCCEEDED(rv))
514 nsLogDllMsg(dll, "AutoUnregistration succeeded for");
515 else
516 nsLogDllMsg(dll, "AutoUnregistration FAILED for");
517
518 if (NS_FAILED(rv))
519 return rv;
520
521 // Remove any autoreg info about this dll
522 nsCStringKey key(persistentDescriptor);
523 mDllStore.RemoveAndDelete(&key);
524
525 nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(mCompMgr);
526 NS_ASSERTION(manager, "Something is terribly wrong");
527
528 manager->RemoveFileInfo(component, nsnull);
529
530 *unregistered = PR_TRUE;
531 return rv;
532}
533
534nsresult
535nsNativeComponentLoader::AutoRegisterComponent(PRInt32 when,
536 nsIFile *component,
537 PRBool *registered)
538{
539 nsresult rv;
540 if (!registered)
541 return NS_ERROR_NULL_POINTER;
542
543 *registered = PR_FALSE;
544
545 /* VBox: Only one valid suffix exist, so dispense with the the list. */
546#ifdef RT_OS_DARWIN
547# ifdef VBOX_IN_32_ON_64_MAIN_API
548 static const char s_szSuff[] = "-x86.dylib";
549# else
550 static const char s_szSuff[] = ".dylib";
551 static const char s_szSuffInvalid[] = "-x86.dylib";
552# endif
553#elif defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
554# ifdef VBOX_IN_32_ON_64_MAIN_API
555 static const char s_szSuff[] = "-x86.dll";
556# else
557 static const char s_szSuff[] = ".dll";
558 static const char s_szSuffInvalid[] = "-x86.dll";
559# endif
560#else
561# ifdef VBOX_IN_32_ON_64_MAIN_API
562 static const char s_szSuff[] = "-x86.so";
563# else
564 static const char s_szSuff[] = ".so";
565 static const char s_szSuffInvalid[] = "-x86.so";
566# endif
567#endif
568
569 nsCAutoString strLeafName;
570 rv = component->GetNativeLeafName(strLeafName);
571 if (NS_FAILED(rv))
572 return rv;
573 size_t cchLeafName = strLeafName.Length();
574 if ( cchLeafName <= sizeof(s_szSuff)
575 || PL_strcasecmp(strLeafName.get() + cchLeafName - sizeof(s_szSuff) + 1, s_szSuff))
576 {
577 Log(("Skipping '%s'...", strLeafName.get()));
578 return NS_OK; /* skip */
579 }
580#ifndef VBOX_IN_32_ON_64_MAIN_API
581 if ( cchLeafName >= sizeof(s_szSuffInvalid)
582 && !PL_strcasecmp(strLeafName.get() + cchLeafName - sizeof(s_szSuffInvalid) + 1, s_szSuffInvalid))
583 {
584 Log(("Skipping '%s' (#2)...", strLeafName.get()));
585 return NS_OK; /* skip */
586 }
587#endif
588 Log(("... '%s'", strLeafName.get()));
589
590 nsXPIDLCString persistentDescriptor;
591 // what I want to do here is QI for a Component Registration Manager. Since this
592 // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
593 nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
594 if (obsoleteManager)
595 rv = obsoleteManager->RegistryLocationForSpec(component,
596 getter_Copies(persistentDescriptor));
597 if (NS_FAILED(rv))
598 return rv;
599
600 nsCStringKey key(persistentDescriptor);
601
602 // Get the registry representation of the dll, if any
603 nsDll *dll;
604 rv = CreateDll(component, persistentDescriptor, &dll);
605 if (NS_FAILED(rv))
606 return rv;
607
608 if (dll != NULL)
609 {
610 // We already have seen this dll. Check if this dll changed
611 if (!dll->HasChanged())
612 {
613 // Dll hasn't changed. Skip.
614 nsLogDllMsg(dll, "Skipping because nsDll has not changed");
615 *registered = PR_TRUE;
616 return NS_OK;
617 }
618
619 // Aagh! the dll has changed since the last time we saw it.
620 // re-register dll
621
622
623 // Notify observers, if any, of autoregistration work
624 nsCOMPtr<nsIObserverService> observerService =
625 do_GetService("@mozilla.org/observer-service;1", &rv);
626 if (NS_SUCCEEDED(rv))
627 {
628 nsCOMPtr<nsIServiceManager> mgr;
629 rv = NS_GetServiceManager(getter_AddRefs(mgr));
630 if (NS_SUCCEEDED(rv))
631 {
632 // this string can't come from a string bundle, because we
633 // don't have string bundles yet.
634 NS_ConvertASCIItoUCS2 fileName("(no name)");
635
636 // get the file name
637 nsCOMPtr<nsIFile> dllSpec;
638 if (NS_SUCCEEDED(dll->GetDllSpec(getter_AddRefs(dllSpec))) && dllSpec)
639 {
640 dllSpec->GetLeafName(fileName);
641 }
642
643 // this string can't come from a string bundle, because we
644 // don't have string bundles yet.
645 (void) observerService->
646 NotifyObservers(mgr,
647 NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID,
648 PromiseFlatString(NS_LITERAL_STRING("Registering native component ") +
649 fileName).get());
650 }
651 }
652
653 if (dll->IsLoaded())
654 {
655 // We loaded the old version of the dll and now we find that the
656 // on-disk copy if newer. Try to unload the dll.
657 nsCOMPtr<nsIServiceManager> serviceMgr;
658 rv = NS_GetServiceManager(getter_AddRefs(serviceMgr));
659
660 rv = nsFreeLibrary(dll, serviceMgr, when);
661 if (NS_FAILED(rv))
662 {
663 // THIS IS THE WORST SITUATION TO BE IN.
664 // Dll doesn't want to be unloaded. Cannot re-register
665 // this dll.
666 nsLogDllMsg(dll, "Skipping because Dll already loaded. "
667 "Cannot unload either. Hence cannot re-register");
668 return rv;
669 }
670 else {
671 // dll doesn't have a CanUnload proc. Guess it is
672 // ok to unload it.
673 dll->Unload();
674 nsLogDllMsg(dll, "+ Unloading (no canUnloadProc)");
675 }
676
677 } // dll isloaded
678
679 // Sanity.
680 if (dll->IsLoaded())
681 {
682 // We went through all the above to make sure the dll
683 // is unloaded. And here we are with the dll still
684 // loaded. Whoever taught dp programming...
685 nsLogDllMsg(dll, "Skipping because Dll still loaded. Cannot re-register");
686 return NS_ERROR_FAILURE;
687 }
688 } // dll != NULL
689 else
690 {
691 // Create and add the dll to the mDllStore
692 // It is ok to do this even if the creation of nsDll
693 // didnt succeed. That way we wont do this again
694 // when we encounter the same dll.
695 dll = new nsDll(component, this);
696 if (dll == NULL)
697 return NS_ERROR_OUT_OF_MEMORY;
698 mDllStore.Put(&key, (void *) dll);
699 } // dll == NULL
700
701 // Either we are seeing the dll for the first time or the dll has
702 // changed since we last saw it and it is unloaded successfully.
703 //
704 // Now we can try register the dll for sure.
705 nsresult res = SelfRegisterDll(dll, persistentDescriptor, PR_FALSE);
706 if (NS_FAILED(res))
707 {
708 if (res == NS_ERROR_FACTORY_REGISTER_AGAIN) {
709 /* defer for later loading */
710 mDeferredComponents.AppendElement(dll);
711 *registered = PR_TRUE;
712 return NS_OK;
713 } else {
714 nsLogDllMsg(dll, "Skipping because Autoregistration FAILED for");
715 return NS_ERROR_FACTORY_NOT_REGISTERED;
716 }
717 }
718 else
719 {
720 nsLogDllMsg(dll, "Autoregistration Passed for");
721 // Marking dll along with modified time and size in the
722 // registry happens at PlatformRegister(). No need to do it
723 // here again.
724 *registered = PR_TRUE;
725 }
726 return NS_OK;
727}
728
729nsresult
730nsNativeComponentLoader::RegisterDeferredComponents(PRInt32 aWhen,
731 PRBool *aRegistered)
732{
733 Log(("nNCL: registering deferred (%d)\n", mDeferredComponents.Count()));
734
735 *aRegistered = PR_FALSE;
736 if (!mDeferredComponents.Count())
737 return NS_OK;
738
739 for (int i = mDeferredComponents.Count() - 1; i >= 0; i--) {
740 nsDll *dll = NS_STATIC_CAST(nsDll *, mDeferredComponents[i]);
741 nsresult rv = SelfRegisterDll(dll,
742 nsnull,
743 PR_TRUE);
744 if (rv != NS_ERROR_FACTORY_REGISTER_AGAIN) {
745 if (NS_SUCCEEDED(rv))
746 *aRegistered = PR_TRUE;
747 mDeferredComponents.RemoveElementAt(i);
748 }
749 }
750
751 if (*aRegistered)
752 Log(("nNCL: registered deferred, %d left\n", mDeferredComponents.Count()));
753 else
754 Log(("nNCL: didn't register any components, %d left\n", mDeferredComponents.Count()));
755
756 /* are there any fatal errors? */
757 return NS_OK;
758}
759
760nsresult
761nsNativeComponentLoader::OnRegister(const nsIID &aCID, const char *aType,
762 const char *aClassName,
763 const char *aContractID,
764 const char *aLocation,
765 PRBool aReplace,
766 PRBool aPersist)
767{
768 return NS_OK;
769}
770
771nsresult
772nsNativeComponentLoader::UnloadAll(PRInt32 aWhen)
773{
774 Log(("nsNativeComponentLoader: Unloading...."));
775
776 struct freeLibrariesClosure callData;
777 callData.serviceMgr = NULL; // XXX need to get this as a parameter
778 callData.when = aWhen;
779
780 // Cycle through the dlls checking to see if they want to be unloaded
781 mDllStore.Enumerate(nsFreeLibraryEnum, &callData);
782 return NS_OK;
783}
784
785//
786// CreateDll
787// The only way to create a dll or get it from the dll cache. This will
788// be called in multiple situations:
789//
790// 1. Autoregister will create one for each dll it is trying to register. This
791// call will be passing a spec in.
792// {spec, NULL, 0, 0}
793//
794// 2. GetFactory() This will call CreateDll() with a null spec but will give
795// the registry represented name of the dll. If modtime and size are zero,
796// we will go the registry to find the right modtime and size.
797// {NULL, rel:libpref.so, 0, 0}
798//
799// 3. Prepopulation of dllCache A dll object created off a registry entry.
800// Specifically dll name is stored in rel: or abs: or lib: formats in the
801// registry along with its lastModTime and fileSize.
802// {NULL, rel:libpref.so, 8985659, 20987}
803nsresult
804nsNativeComponentLoader::CreateDll(nsIFile *aSpec,
805 const char *aLocation,
806 nsDll **aDll)
807{
808 nsDll *dll;
809 nsCOMPtr<nsIFile> dllSpec;
810 nsCOMPtr<nsIFile> spec;
811 nsresult rv;
812
813 nsCStringKey key(aLocation);
814 dll = (nsDll *)mDllStore.Get(&key);
815 if (dll)
816 {
817 *aDll = dll;
818 return NS_OK;
819 }
820
821 if (!aSpec)
822 {
823 // what I want to do here is QI for a Component Registration Manager. Since this
824 // has not been invented yet, QI to the obsolete manager. Kids, don't do this at home.
825 nsCOMPtr<nsIComponentManagerObsolete> obsoleteManager = do_QueryInterface(mCompMgr, &rv);
826 if (obsoleteManager)
827 rv = obsoleteManager->SpecForRegistryLocation(aLocation,
828 getter_AddRefs(spec));
829 if (NS_FAILED(rv))
830 return rv;
831 }
832 else
833 {
834 spec = aSpec;
835 }
836
837 if (!dll)
838 {
839 dll = new nsDll(spec, this);
840 if (!dll)
841 return NS_ERROR_OUT_OF_MEMORY;
842 }
843
844 *aDll = dll;
845 mDllStore.Put(&key, dll);
846 return NS_OK;
847}
848
849nsresult
850nsNativeComponentLoader::GetFactoryFromModule(nsDll *aDll, const nsCID &aCID,
851 nsIFactory **aFactory)
852{
853 nsresult rv;
854
855 nsCOMPtr<nsIModule> module;
856 rv = aDll->GetModule(mCompMgr, getter_AddRefs(module));
857
858 if (NS_FAILED(rv))
859 return rv;
860
861 return module->GetClassObject(mCompMgr, aCID, NS_GET_IID(nsIFactory),
862 (void **)aFactory);
863}
864
865
866NS_IMETHODIMP
867nsNativeComponentLoader::AddDependentLibrary(nsIFile* aFile, const char* libName)
868{
869 nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(mCompMgr);
870 if (!manager)
871 {
872 NS_WARNING("Something is terribly wrong");
873 return NS_ERROR_FAILURE;
874 }
875
876 // the native component loader uses the optional data
877 // to store a space delimited list of dependent library
878 // names
879
880 if (!libName)
881 {
882 manager->SetOptionalData(aFile, nsnull, nsnull);
883 return NS_OK;
884 }
885
886 nsXPIDLCString data;
887 manager->GetOptionalData(aFile, nsnull, getter_Copies(data));
888
889 if (!data.IsEmpty())
890 data.AppendLiteral(" ");
891
892 data.Append(nsDependentCString(libName));
893
894 manager->SetOptionalData(aFile, nsnull, data);
895 return NS_OK;
896}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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