Back to index

lightning-sunbird  0.9+nobinonly
nsEmbedAPI.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is the Mozilla browser.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications, Inc.
00020  * Portions created by the Initial Developer are Copyright (C) 1999
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsIServiceManager.h"
00040 #include "nsIComponentManager.h"
00041 #include "nsIComponentRegistrar.h"
00042 #include "nsIAppStartupNotifier.h"
00043 #include "nsIStringBundle.h"
00044 
00045 #include "nsIDirectoryService.h"
00046 #include "nsDirectoryServiceDefs.h"
00047 
00048 #include "nsXPCOM.h"
00049 #include "nsEmbedAPI.h"
00050 
00051 static nsIServiceManager *sServiceManager = nsnull;
00052 static PRBool             sRegistryInitializedFlag = PR_FALSE;
00053 static PRUint32           sInitCounter = 0;
00054 
00055 #define HACK_AROUND_THREADING_ISSUES
00056 //#define HACK_AROUND_NONREENTRANT_INITXPCOM
00057 
00058 #ifdef HACK_AROUND_NONREENTRANT_INITXPCOM
00059 // XXX hack class to clean up XPCOM when this module is unloaded
00060 class XPCOMCleanupHack
00061 {
00062 public:
00063     PRBool mCleanOnExit;
00064 
00065     XPCOMCleanupHack() : mCleanOnExit(PR_FALSE) {}
00066     ~XPCOMCleanupHack()
00067     {
00068         if (mCleanOnExit)
00069         {
00070             if (sInitCounter > 0)
00071             {
00072                 sInitCounter = 1;
00073                 NS_TermEmbedding();
00074             }
00075             // XXX Global destructors and NS_ShutdownXPCOM don't seem to mix
00076 //          NS_ShutdownXPCOM(sServiceManager);
00077         }
00078     }
00079 };
00080 static PRBool sXPCOMInitializedFlag = PR_FALSE;
00081 static XPCOMCleanupHack sXPCOMCleanupHack;
00082 #endif
00083 
00084 
00085 NS_METHOD
00086 NS_InitEmbedding(nsILocalFile *mozBinDirectory,
00087                  nsIDirectoryServiceProvider *appFileLocProvider,
00088                  nsStaticModuleInfo const *aStaticComponents,
00089                  PRUint32 aStaticComponentCount)
00090 {
00091     nsresult rv;
00092 
00093     // Reentrant calls to this method do nothing except increment a counter
00094     sInitCounter++;
00095     if (sInitCounter > 1)
00096         return NS_OK;
00097 
00098     // Initialise XPCOM
00099 #ifdef HACK_AROUND_NONREENTRANT_INITXPCOM
00100     // Can't call NS_InitXPCom more than once or things go boom!
00101     if (!sXPCOMInitializedFlag)
00102 #endif
00103     {
00104         // Initialise XPCOM
00105         rv = NS_InitXPCOM3(&sServiceManager, mozBinDirectory, appFileLocProvider,
00106                            aStaticComponents, aStaticComponentCount);
00107         NS_ENSURE_SUCCESS(rv, rv);
00108                 
00109 #ifdef HACK_AROUND_NONREENTRANT_INITXPCOM
00110         sXPCOMInitializedFlag = PR_TRUE;
00111         sXPCOMCleanupHack.mCleanOnExit = PR_TRUE;
00112 #endif
00113     }
00114     // Register components
00115     if (!sRegistryInitializedFlag)
00116     {
00117 #ifdef DEBUG
00118         nsIComponentRegistrar *registrar;
00119         rv = sServiceManager->QueryInterface(NS_GET_IID(nsIComponentRegistrar),
00120                                              (void **) &registrar);
00121         if (NS_FAILED(rv))
00122         {
00123             NS_WARNING("Could not QI to registrar");
00124             return rv;
00125         }
00126         rv = registrar->AutoRegister(nsnull);
00127         if (NS_FAILED(rv))
00128         {
00129             NS_WARNING("Could not AutoRegister");
00130         }
00131         else
00132         {
00133             // If the application is using an GRE, then, auto register components
00134             // in the GRE directory as well.
00135             //
00136             // The application indicates that it's using an GRE by returning a
00137             // valid nsIFile when queried (via appFileLocProvider) for the
00138             // NS_GRE_DIR atom as shown below
00139 
00140             if (appFileLocProvider)
00141             {
00142                 nsIFile *greDir = nsnull;
00143                 PRBool persistent = PR_TRUE;
00144 
00145                 appFileLocProvider->GetFile(NS_GRE_DIR, &persistent,
00146                                             &greDir);
00147                 if (greDir)
00148                 {
00149                     rv = registrar->AutoRegister(greDir);
00150                     if (NS_FAILED(rv))
00151                         NS_WARNING("Could not AutoRegister GRE components");
00152                     NS_RELEASE(greDir);
00153                 }
00154             }
00155         }
00156         NS_RELEASE(registrar);
00157         if (NS_FAILED(rv))
00158             return rv;
00159 #endif
00160         sRegistryInitializedFlag = PR_TRUE;
00161     }
00162 
00163     nsIComponentManager *compMgr;
00164     rv = sServiceManager->QueryInterface(NS_GET_IID(nsIComponentManager),
00165                                          (void **) &compMgr);
00166     if (NS_FAILED(rv))
00167         return rv;
00168 
00169     nsIObserver *startupNotifier;
00170     rv = compMgr->CreateInstanceByContractID(NS_APPSTARTUPNOTIFIER_CONTRACTID,
00171                                              NULL,
00172                                              NS_GET_IID(nsIObserver),
00173                                              (void **) &startupNotifier);
00174     NS_RELEASE(compMgr);
00175     if (NS_FAILED(rv))
00176         return rv;
00177 
00178          startupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull);
00179     NS_RELEASE(startupNotifier);
00180 
00181 #ifdef HACK_AROUND_THREADING_ISSUES
00182     // XXX force certain objects to be created on the main thread
00183     nsIStringBundleService *bundleService;
00184     rv = sServiceManager->GetServiceByContractID(NS_STRINGBUNDLE_CONTRACTID,
00185                                                  NS_GET_IID(nsIStringBundleService),
00186                                                  (void **) &bundleService);
00187     if (NS_SUCCEEDED(rv))
00188     {
00189         nsIStringBundle *stringBundle;
00190         const char propertyURL[] = "chrome://necko/locale/necko.properties";
00191         rv = bundleService->CreateBundle(propertyURL, &stringBundle);
00192         NS_RELEASE(stringBundle);
00193         NS_RELEASE(bundleService);
00194     }
00195 #endif
00196 
00197     return NS_OK;
00198 }
00199 
00200 NS_METHOD
00201 NS_TermEmbedding()
00202 {
00203     // Reentrant calls to this method do nothing except decrement a counter
00204     if (sInitCounter > 1)
00205     {
00206         sInitCounter--;
00207         return NS_OK;
00208     }
00209     sInitCounter = 0;
00210 
00211     NS_IF_RELEASE(sServiceManager);
00212 
00213     // Terminate XPCOM & cleanup
00214 #ifndef HACK_AROUND_NONREENTRANT_INITXPCOM
00215     nsresult rv = NS_ShutdownXPCOM(sServiceManager);
00216     NS_ENSURE_SUCCESS(rv, rv);
00217 #endif
00218 
00219     return NS_OK;
00220 }