VirtualBox

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

最後變更 在這個檔案從104411是 102458,由 vboxsync 提交於 15 月 前

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

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