Back to index

lightning-sunbird  0.9+nobinonly
qgeckoglobals.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 mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  *  Zack Rusin <zack@kde.org>.
00020  * Portions created by the Initial Developer are Copyright (C) 2004
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Lars Knoll <knoll@kde.org>
00025  *   Zack Rusin <zack@kde.org>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 #include "qgeckoglobals.h"
00041 
00042 #include "qgeckoembed.h"
00043 #include "EmbedWindow.h"
00044 #include "QtPromptService.h"
00045 
00046 #include "nsIAppShell.h"
00047 #include <nsIDocShell.h>
00048 #include <nsIWebProgress.h>
00049 #include <nsIWebNavigation.h>
00050 #include <nsIWebBrowser.h>
00051 #include <nsISHistory.h>
00052 #include <nsIWebBrowserChrome.h>
00053 #include "nsIWidget.h"
00054 #include "nsCRT.h"
00055 #include <nsIWindowWatcher.h>
00056 #include <nsILocalFile.h>
00057 #include <nsEmbedAPI.h>
00058 #include <nsWidgetsCID.h>
00059 #include <nsIDOMUIEvent.h>
00060 
00061 #include <nsIInterfaceRequestor.h>
00062 #include <nsIComponentManager.h>
00063 #include <nsIFocusController.h>
00064 #include <nsProfileDirServiceProvider.h>
00065 #include <nsIGenericFactory.h>
00066 #include <nsIComponentRegistrar.h>
00067 #include <nsVoidArray.h>
00068 #include <nsIDOMBarProp.h>
00069 #include <nsIDOMWindow.h>
00070 #include <nsIDOMEventReceiver.h>
00071 
00072 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
00073 
00074 PRUint32     QGeckoGlobals::sWidgetCount = 0;
00075 char        *QGeckoGlobals::sCompPath    = nsnull;
00076 nsIAppShell *QGeckoGlobals::sAppShell    = nsnull;
00077 char        *QGeckoGlobals::sProfileDir  = nsnull;
00078 char        *QGeckoGlobals::sProfileName = nsnull;
00079 nsVoidArray *QGeckoGlobals::sWindowList  = nsnull;
00080 nsIDirectoryServiceProvider *QGeckoGlobals::sAppFileLocProvider = nsnull;
00081 nsProfileDirServiceProvider *QGeckoGlobals::sProfileDirServiceProvider = nsnull;
00082 
00083 #define NS_PROMPTSERVICE_CID \
00084  {0x95611356, 0xf583, 0x46f5, {0x81, 0xff, 0x4b, 0x3e, 0x01, 0x62, 0xc6, 0x19}}
00085 
00086 NS_GENERIC_FACTORY_CONSTRUCTOR(QtPromptService)
00087 
00088 static const nsModuleComponentInfo defaultAppComps[] = {
00089   {
00090     "Prompt Service",
00091     NS_PROMPTSERVICE_CID,
00092     "@mozilla.org/embedcomp/prompt-service;1",
00093     QtPromptServiceConstructor
00094   }
00095 };
00096 
00097 void
00098 QGeckoGlobals::pushStartup()
00099 {
00100     // increment the number of widgets
00101     sWidgetCount++;
00102 
00103     // if this is the first widget, fire up xpcom
00104     if (sWidgetCount == 1) {
00105         nsresult rv;
00106         nsCOMPtr<nsILocalFile> binDir;
00107 
00108         if (sCompPath) {
00109             rv = NS_NewNativeLocalFile(nsDependentCString(sCompPath), 1, getter_AddRefs(binDir));
00110             if (NS_FAILED(rv))
00111                 return;
00112         }
00113 
00114         rv = NS_InitEmbedding(binDir, sAppFileLocProvider);
00115         if (NS_FAILED(rv))
00116             return;
00117 
00118         // we no longer need a reference to the DirectoryServiceProvider
00119         if (sAppFileLocProvider) {
00120             NS_RELEASE(sAppFileLocProvider);
00121             sAppFileLocProvider = nsnull;
00122         }
00123 
00124         rv = startupProfile();
00125         NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Warning: Failed to start up profiles.\n");
00126 
00127         rv = registerAppComponents();
00128         NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Warning: Failed to register app components.\n");
00129 
00130         // XXX startup appshell service?
00131 
00132         nsCOMPtr<nsIAppShell> appShell;
00133         appShell = do_CreateInstance(kAppShellCID);
00134         if (!appShell) {
00135             NS_WARNING("Failed to create appshell in QGeckoGlobals::pushStartup!\n");
00136             return;
00137         }
00138         sAppShell = appShell.get();
00139         NS_ADDREF(sAppShell);
00140         sAppShell->Create(0, nsnull);
00141         sAppShell->Spinup();
00142     }
00143 }
00144 
00145 void
00146 QGeckoGlobals::popStartup()
00147 {
00148     sWidgetCount--;
00149     if (sWidgetCount == 0) {
00150         // shut down the profiles
00151         shutdownProfile();
00152 
00153         if (sAppShell) {
00154             // Shutdown the appshell service.
00155             sAppShell->Spindown();
00156             NS_RELEASE(sAppShell);
00157             sAppShell = 0;
00158         }
00159 
00160         // shut down XPCOM/Embedding
00161         NS_TermEmbedding();
00162     }
00163 }
00164 
00165 void
00166 QGeckoGlobals::setCompPath(const char *aPath)
00167 {
00168     if (sCompPath)
00169         free(sCompPath);
00170     if (aPath)
00171         sCompPath = strdup(aPath);
00172     else
00173         sCompPath = nsnull;
00174 }
00175 
00176 void
00177 QGeckoGlobals::setAppComponents(const nsModuleComponentInfo *,
00178                              int)
00179 {
00180 }
00181 
00182 void
00183 QGeckoGlobals::setProfilePath(const char *aDir, const char *aName)
00184 {
00185     if (sProfileDir) {
00186         nsMemory::Free(sProfileDir);
00187         sProfileDir = nsnull;
00188     }
00189 
00190     if (sProfileName) {
00191         nsMemory::Free(sProfileName);
00192         sProfileName = nsnull;
00193     }
00194 
00195     if (aDir)
00196         sProfileDir = (char *)nsMemory::Clone(aDir, strlen(aDir) + 1);
00197 
00198     if (aName)
00199         sProfileName = (char *)nsMemory::Clone(aName, strlen(aName) + 1);
00200 }
00201 
00202 void
00203 QGeckoGlobals::setDirectoryServiceProvider(nsIDirectoryServiceProvider
00204                                         *appFileLocProvider)
00205 {
00206     if (sAppFileLocProvider)
00207         NS_RELEASE(sAppFileLocProvider);
00208 
00209     if (appFileLocProvider) {
00210         sAppFileLocProvider = appFileLocProvider;
00211         NS_ADDREF(sAppFileLocProvider);
00212     }
00213 }
00214 
00215 
00216 /* static */
00217 int
00218 QGeckoGlobals::startupProfile(void)
00219 {
00220     // initialize profiles
00221     if (sProfileDir && sProfileName) {
00222         nsresult rv;
00223         nsCOMPtr<nsILocalFile> profileDir;
00224         NS_NewNativeLocalFile(nsDependentCString(sProfileDir), PR_TRUE,
00225                               getter_AddRefs(profileDir));
00226         if (!profileDir)
00227             return NS_ERROR_FAILURE;
00228         rv = profileDir->AppendNative(nsDependentCString(sProfileName));
00229         if (NS_FAILED(rv))
00230             return NS_ERROR_FAILURE;
00231 
00232         nsCOMPtr<nsProfileDirServiceProvider> locProvider;
00233         NS_NewProfileDirServiceProvider(PR_TRUE, getter_AddRefs(locProvider));
00234         if (!locProvider)
00235             return NS_ERROR_FAILURE;
00236         rv = locProvider->Register();
00237         if (NS_FAILED(rv))
00238             return rv;
00239         rv = locProvider->SetProfileDir(profileDir);
00240         if (NS_FAILED(rv))
00241             return rv;
00242         // Keep a ref so we can shut it down.
00243         NS_ADDREF(sProfileDirServiceProvider = locProvider);
00244     }
00245     return NS_OK;
00246 }
00247 
00248 /* static */
00249 void
00250 QGeckoGlobals::shutdownProfile(void)
00251 {
00252     if (sProfileDirServiceProvider) {
00253         sProfileDirServiceProvider->Shutdown();
00254         NS_RELEASE(sProfileDirServiceProvider);
00255         sProfileDirServiceProvider = 0;
00256     }
00257 }
00258 
00259 /* static */
00260 int
00261 QGeckoGlobals::registerAppComponents()
00262 {
00263   nsCOMPtr<nsIComponentRegistrar> cr;
00264   nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(cr));
00265   NS_ENSURE_SUCCESS(rv, rv);
00266 
00267   int numAppComps = sizeof(defaultAppComps) / sizeof(nsModuleComponentInfo);
00268   for (int i = 0; i < numAppComps; ++i) {
00269     nsCOMPtr<nsIGenericFactory> componentFactory;
00270     rv = NS_NewGenericFactory(getter_AddRefs(componentFactory),
00271                               &(defaultAppComps[i]));
00272     if (NS_FAILED(rv)) {
00273       NS_WARNING("Unable to create factory for component");
00274       continue;  // don't abort registering other components
00275     }
00276 
00277     rv = cr->RegisterFactory(defaultAppComps[i].mCID, defaultAppComps[i].mDescription,
00278                              defaultAppComps[i].mContractID, componentFactory);
00279     NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to register factory for component");
00280   }
00281 
00282   return rv;
00283 }
00284 
00285 void QGeckoGlobals::initializeGlobalObjects()
00286 {
00287     if (!sWindowList) {
00288         sWindowList = new nsVoidArray();
00289     }
00290 }
00291 
00292 void QGeckoGlobals::addEngine(QGeckoEmbed *embed)
00293 {
00294     sWindowList->AppendElement(embed);
00295 }
00296 
00297 void QGeckoGlobals::removeEngine(QGeckoEmbed *embed)
00298 {
00299     sWindowList->RemoveElement(embed);
00300 }
00301 
00302 QGeckoEmbed *QGeckoGlobals::findPrivateForBrowser(nsIWebBrowserChrome *aBrowser)
00303 {
00304     if (!sWindowList)
00305         return nsnull;
00306 
00307     // Get the number of browser windows.
00308     PRInt32 count = sWindowList->Count();
00309     // This function doesn't get called very often at all ( only when
00310     // creating a new window ) so it's OK to walk the list of open
00311     // windows.
00312     for (int i = 0; i < count; i++) {
00313         QGeckoEmbed *tmpPrivate = NS_STATIC_CAST(QGeckoEmbed *,
00314                                                 sWindowList->ElementAt(i));
00315         // get the browser object for that window
00316         nsIWebBrowserChrome *chrome = NS_STATIC_CAST(nsIWebBrowserChrome *,
00317                                                      tmpPrivate->window());
00318         if (chrome == aBrowser)
00319             return tmpPrivate;
00320     }
00321 
00322     return nsnull;
00323 }