On x86 compilers without fastcall, simulate it when invoking traces and un-simulate...
[wine-gecko.git] / xpcom / glue / nsGenericFactory.cpp
blob007bcffc88785c5338452bb149c945d922cfb208
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
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/
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.
15 * The Original Code is mozilla.org code.
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.
22 * Contributor(s):
23 * Pierre Phaneuf <pp@ludusdesign.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
40 // DO NOT COPY THIS CODE INTO YOUR SOURCE! USE NS_IMPL_NSGETMODULE()
42 #include "nsGenericFactory.h"
43 #include "nsMemory.h"
44 #include "nsCOMPtr.h"
45 #include "nsIComponentManager.h"
46 #include "nsIComponentRegistrar.h"
47 #include "nsIProgrammingLanguage.h"
49 #ifdef XPCOM_GLUE
50 #include "nsXPCOMGlue.h"
51 #include "nsXPCOMPrivate.h"
52 #endif
54 nsGenericFactory::nsGenericFactory(const nsModuleComponentInfo *info)
55 : mInfo(info)
57 if (mInfo && mInfo->mClassInfoGlobal)
58 *mInfo->mClassInfoGlobal = static_cast<nsIClassInfo *>(this);
61 nsGenericFactory::~nsGenericFactory()
63 if (mInfo) {
64 if (mInfo->mFactoryDestructor)
65 mInfo->mFactoryDestructor();
66 if (mInfo->mClassInfoGlobal)
67 *mInfo->mClassInfoGlobal = 0;
71 NS_IMPL_THREADSAFE_ISUPPORTS3(nsGenericFactory,
72 nsIGenericFactory,
73 nsIFactory,
74 nsIClassInfo)
76 NS_IMETHODIMP nsGenericFactory::CreateInstance(nsISupports *aOuter,
77 REFNSIID aIID, void **aResult)
79 if (mInfo->mConstructor) {
80 return mInfo->mConstructor(aOuter, aIID, aResult);
83 return NS_ERROR_FACTORY_NOT_REGISTERED;
86 NS_IMETHODIMP nsGenericFactory::LockFactory(PRBool aLock)
88 // XXX do we care if (mInfo->mFlags & THREADSAFE)?
89 return NS_OK;
92 NS_IMETHODIMP nsGenericFactory::GetInterfaces(PRUint32 *countp,
93 nsIID* **array)
95 if (!mInfo->mGetInterfacesProc) {
96 *countp = 0;
97 *array = nsnull;
98 return NS_OK;
100 return mInfo->mGetInterfacesProc(countp, array);
103 NS_IMETHODIMP nsGenericFactory::GetHelperForLanguage(PRUint32 language,
104 nsISupports **helper)
106 if (mInfo->mGetLanguageHelperProc)
107 return mInfo->mGetLanguageHelperProc(language, helper);
108 *helper = nsnull;
109 return NS_OK;
112 NS_IMETHODIMP nsGenericFactory::GetContractID(char **aContractID)
114 if (mInfo->mContractID) {
115 *aContractID = (char *)nsMemory::Alloc(strlen(mInfo->mContractID) + 1);
116 if (!*aContractID)
117 return NS_ERROR_OUT_OF_MEMORY;
118 strcpy(*aContractID, mInfo->mContractID);
119 } else {
120 *aContractID = nsnull;
122 return NS_OK;
125 NS_IMETHODIMP nsGenericFactory::GetClassDescription(char * *aClassDescription)
127 if (mInfo->mDescription) {
128 *aClassDescription = (char *)
129 nsMemory::Alloc(strlen(mInfo->mDescription) + 1);
130 if (!*aClassDescription)
131 return NS_ERROR_OUT_OF_MEMORY;
132 strcpy(*aClassDescription, mInfo->mDescription);
133 } else {
134 *aClassDescription = nsnull;
136 return NS_OK;
139 NS_IMETHODIMP nsGenericFactory::GetClassID(nsCID * *aClassID)
141 *aClassID =
142 reinterpret_cast<nsCID*>
143 (nsMemory::Clone(&mInfo->mCID, sizeof mInfo->mCID));
144 if (! *aClassID)
145 return NS_ERROR_OUT_OF_MEMORY;
146 return NS_OK;
149 NS_IMETHODIMP nsGenericFactory::GetClassIDNoAlloc(nsCID *aClassID)
151 *aClassID = mInfo->mCID;
152 return NS_OK;
155 NS_IMETHODIMP nsGenericFactory::GetImplementationLanguage(PRUint32 *langp)
157 *langp = nsIProgrammingLanguage::CPLUSPLUS;
158 return NS_OK;
161 NS_IMETHODIMP nsGenericFactory::GetFlags(PRUint32 *flagsp)
163 *flagsp = mInfo->mFlags;
164 return NS_OK;
167 // nsIGenericFactory: component-info accessors
168 NS_IMETHODIMP nsGenericFactory::SetComponentInfo(const nsModuleComponentInfo *info)
170 if (mInfo && mInfo->mClassInfoGlobal)
171 *mInfo->mClassInfoGlobal = 0;
172 mInfo = info;
173 if (mInfo && mInfo->mClassInfoGlobal)
174 *mInfo->mClassInfoGlobal = static_cast<nsIClassInfo *>(this);
175 return NS_OK;
178 NS_IMETHODIMP nsGenericFactory::GetComponentInfo(const nsModuleComponentInfo **infop)
180 *infop = mInfo;
181 return NS_OK;
184 NS_METHOD nsGenericFactory::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
186 // sorry, aggregation not spoken here.
187 nsresult res = NS_ERROR_NO_AGGREGATION;
188 if (outer == NULL) {
189 nsGenericFactory* factory = new nsGenericFactory;
190 if (factory != NULL) {
191 res = factory->QueryInterface(aIID, aInstancePtr);
192 if (res != NS_OK)
193 delete factory;
194 } else {
195 res = NS_ERROR_OUT_OF_MEMORY;
198 return res;
201 NS_COM_GLUE nsresult
202 NS_NewGenericFactory(nsIGenericFactory* *result,
203 const nsModuleComponentInfo *info)
205 nsresult rv;
206 nsIGenericFactory* fact;
207 rv = nsGenericFactory::Create(NULL, NS_GET_IID(nsIGenericFactory), (void**)&fact);
208 if (NS_FAILED(rv)) return rv;
209 rv = fact->SetComponentInfo(info);
210 if (NS_FAILED(rv)) goto error;
211 *result = fact;
212 return rv;
214 error:
215 NS_RELEASE(fact);
216 return rv;
219 ////////////////////////////////////////////////////////////////////////////////
221 nsGenericModule::nsGenericModule(const char* moduleName, PRUint32 componentCount,
222 const nsModuleComponentInfo* components,
223 nsModuleConstructorProc ctor,
224 nsModuleDestructorProc dtor)
225 : mInitialized(PR_FALSE),
226 mModuleName(moduleName),
227 mComponentCount(componentCount),
228 mComponents(components),
229 mFactoriesNotToBeRegistered(nsnull),
230 mCtor(ctor),
231 mDtor(dtor)
235 nsGenericModule::~nsGenericModule()
237 Shutdown();
239 #ifdef XPCOM_GLUE
240 XPCOMGlueShutdown();
241 #endif
245 NS_IMPL_THREADSAFE_ISUPPORTS1(nsGenericModule, nsIModule)
247 nsresult
248 nsGenericModule::AddFactoryNode(nsIGenericFactory* fact)
250 if (!fact)
251 return NS_ERROR_FAILURE;
253 FactoryNode *node = new FactoryNode(fact, mFactoriesNotToBeRegistered);
254 if (!node)
255 return NS_ERROR_OUT_OF_MEMORY;
257 mFactoriesNotToBeRegistered = node;
258 return NS_OK;
262 // Perform our one-time intialization for this module
263 nsresult
264 nsGenericModule::Initialize(nsIComponentManager *compMgr)
266 nsresult rv;
268 if (mInitialized) {
269 return NS_OK;
272 if (mCtor) {
273 rv = mCtor(this);
274 if (NS_FAILED(rv))
275 return rv;
279 #ifdef XPCOM_GLUE
280 rv = XPCOMGlueStartup(".");
281 if (NS_FAILED(rv))
282 return rv;
283 #endif
285 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(compMgr, &rv);
286 if (NS_FAILED(rv))
287 return rv;
289 // Eagerly populate factory/class object hash for entries
290 // without constructors. If we didn't, the class object would
291 // never get created. Also create the factory, which doubles
292 // as the class object, if the EAGER_CLASSINFO flag was given.
293 // This allows objects to be created (within their modules)
294 // via operator new rather than CreateInstance, yet still be
295 // QI'able to nsIClassInfo.
296 const nsModuleComponentInfo* desc = mComponents;
297 for (PRUint32 i = 0; i < mComponentCount; i++) {
298 if (!desc->mConstructor ||
299 (desc->mFlags & nsIClassInfo::EAGER_CLASSINFO)) {
300 nsCOMPtr<nsIGenericFactory> fact;
301 nsresult rv = NS_NewGenericFactory(getter_AddRefs(fact), desc);
302 if (NS_FAILED(rv)) return rv;
304 // if we don't have a mConstructor, then we should not populate
305 // the component manager.
306 if (!desc->mConstructor) {
307 rv = AddFactoryNode(fact);
308 } else {
309 rv = registrar->RegisterFactory(desc->mCID,
310 desc->mDescription,
311 desc->mContractID,
312 fact);
314 if (NS_FAILED(rv)) return rv;
316 desc++;
319 mInitialized = PR_TRUE;
320 return NS_OK;
323 // Shutdown this module, releasing all of the module resources
324 void
325 nsGenericModule::Shutdown()
327 // Free cached factories that were not registered.
328 FactoryNode* node;
329 while (mFactoriesNotToBeRegistered)
331 node = mFactoriesNotToBeRegistered->mNext;
332 delete mFactoriesNotToBeRegistered;
333 mFactoriesNotToBeRegistered = node;
336 if (mInitialized) {
337 mInitialized = PR_FALSE;
339 if (mDtor)
340 mDtor(this);
344 // Create a factory object for creating instances of aClass.
345 NS_IMETHODIMP
346 nsGenericModule::GetClassObject(nsIComponentManager *aCompMgr,
347 const nsCID& aClass,
348 const nsIID& aIID,
349 void** r_classObj)
351 nsresult rv;
353 // Defensive programming: Initialize *r_classObj in case of error below
354 if (!r_classObj) {
355 return NS_ERROR_INVALID_POINTER;
357 *r_classObj = NULL;
359 // Do one-time-only initialization if necessary
360 if (!mInitialized) {
361 rv = Initialize(aCompMgr);
362 if (NS_FAILED(rv)) {
363 // Initialization failed! yikes!
364 return rv;
368 // Choose the appropriate factory, based on the desired instance
369 // class type (aClass).
370 const nsModuleComponentInfo* desc = mComponents;
371 for (PRUint32 i = 0; i < mComponentCount; i++) {
372 if (desc->mCID.Equals(aClass)) {
373 nsCOMPtr<nsIGenericFactory> fact;
374 rv = NS_NewGenericFactory(getter_AddRefs(fact), desc);
375 if (NS_FAILED(rv)) return rv;
376 return fact->QueryInterface(aIID, r_classObj);
378 desc++;
380 // not found in descriptions
381 return NS_ERROR_FACTORY_NOT_REGISTERED;
384 NS_IMETHODIMP
385 nsGenericModule::RegisterSelf(nsIComponentManager *aCompMgr,
386 nsIFile* aPath,
387 const char* registryLocation,
388 const char* componentType)
390 nsresult rv = NS_OK;
392 #ifdef DEBUG
393 printf_stderr("*** Registering components in: %s\n", mModuleName);
394 #endif
396 const nsModuleComponentInfo* cp = mComponents;
397 for (PRUint32 i = 0; i < mComponentCount; i++) {
398 // Register the component only if it has a constructor
399 if (cp->mConstructor) {
400 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(aCompMgr, &rv);
401 if (registrar)
402 rv = registrar->RegisterFactoryLocation(cp->mCID,
403 cp->mDescription,
404 cp->mContractID,
405 aPath,
406 registryLocation,
407 componentType);
408 if (NS_FAILED(rv)) {
409 #ifdef DEBUG
410 printf_stderr("nsGenericModule %s: unable to register %s component => %x\n",
411 mModuleName?mModuleName:"(null)", cp->mDescription?cp->mDescription:"(null)", rv);
412 #endif
413 break;
416 // Call the registration hook of the component, if any
417 if (cp->mRegisterSelfProc)
419 rv = cp->mRegisterSelfProc(aCompMgr, aPath, registryLocation,
420 componentType, cp);
421 if (NS_FAILED(rv)) {
422 #ifdef DEBUG
423 printf_stderr("nsGenericModule %s: Register hook for %s component returned error => %x\n",
424 mModuleName?mModuleName:"(null)", cp->mDescription?cp->mDescription:"(null)", rv);
425 #endif
426 break;
429 cp++;
432 return rv;
435 NS_IMETHODIMP
436 nsGenericModule::UnregisterSelf(nsIComponentManager* aCompMgr,
437 nsIFile* aPath,
438 const char* registryLocation)
440 #ifdef DEBUG
441 printf_stderr("*** Unregistering components in: %s\n", mModuleName);
442 #endif
443 const nsModuleComponentInfo* cp = mComponents;
444 for (PRUint32 i = 0; i < mComponentCount; i++) {
445 // Call the unregistration hook of the component, if any
446 if (cp->mUnregisterSelfProc)
448 cp->mUnregisterSelfProc(aCompMgr, aPath, registryLocation, cp);
451 // Unregister the component
452 nsresult rv;
453 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(aCompMgr, &rv);
454 if (registrar)
455 rv = registrar->UnregisterFactoryLocation(cp->mCID, aPath);
456 if (NS_FAILED(rv)) {
457 #ifdef DEBUG
458 printf_stderr("nsGenericModule %s: unable to unregister %s component => %x\n",
459 mModuleName, cp->mDescription, rv);
460 #endif
462 cp++;
465 return NS_OK;
468 NS_IMETHODIMP
469 nsGenericModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload)
471 if (!okToUnload) {
472 return NS_ERROR_INVALID_POINTER;
474 *okToUnload = PR_FALSE;
475 return NS_ERROR_FAILURE;
478 NS_COM_GLUE nsresult
479 NS_NewGenericModule2(nsModuleInfo const *info, nsIModule* *result)
481 nsresult rv = NS_OK;
483 // Create and initialize the module instance
484 nsGenericModule *m =
485 new nsGenericModule(info->mModuleName, info->mCount, info->mComponents,
486 info->mCtor, info->mDtor);
488 if (!m)
489 return NS_ERROR_OUT_OF_MEMORY;
491 // Increase refcnt and store away nsIModule interface to m in result
492 NS_ADDREF(*result = m);
493 return rv;
496 NS_COM_GLUE nsresult
497 NS_NewGenericModule(const char* moduleName,
498 PRUint32 componentCount,
499 nsModuleComponentInfo* components,
500 nsModuleDestructorProc dtor,
501 nsIModule* *result)
503 nsModuleInfo info;
504 memset(&info, 0, sizeof(info));
506 info.mVersion = NS_MODULEINFO_VERSION;
507 info.mModuleName = moduleName;
508 info.mComponents = components;
509 info.mCount = componentCount;
510 info.mDtor = dtor;
512 return NS_NewGenericModule2(&info, result);
515 ////////////////////////////////////////////////////////////////////////////////