VirtualBox

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

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

libs/xpcom: Cleanup nsNativeComponentLoader.cpp, convert from PR_LOG to IPRT's logging infrastructure, bugref:10545

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

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