Back to index

lightning-sunbird  0.9+nobinonly
winEmbedFileLocProvider.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code, released
00016  * March 31, 1998.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 2000
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Conrad Carlen <conrad@ingress.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039  
00040 #include "winEmbedFileLocProvider.h"
00041 #include "nsAppDirectoryServiceDefs.h"
00042 #include "nsDirectoryServiceDefs.h"
00043 #include "nsILocalFile.h"
00044 #include "nsString.h"
00045 #include "nsXPIDLString.h"
00046 #include "nsCRT.h"
00047 
00048 
00049 #include <windows.h>
00050 #include <shlobj.h>
00051 
00052  
00053 // WARNING: These hard coded names need to go away. They need to
00054 // come from localizable resources
00055 #define APP_REGISTRY_NAME NS_LITERAL_CSTRING("registry.dat")
00056 
00057 #define PROFILE_ROOT_DIR_NAME       NS_LITERAL_CSTRING("Profiles")
00058 #define DEFAULTS_DIR_NAME           NS_LITERAL_CSTRING("defaults")
00059 #define DEFAULTS_PREF_DIR_NAME      NS_LITERAL_CSTRING("pref")
00060 #define DEFAULTS_PROFILE_DIR_NAME   NS_LITERAL_CSTRING("profile")
00061 #define RES_DIR_NAME                NS_LITERAL_CSTRING("res")
00062 #define CHROME_DIR_NAME             NS_LITERAL_CSTRING("chrome")
00063 #define PLUGINS_DIR_NAME            NS_LITERAL_CSTRING("plugins")
00064 #define SEARCH_DIR_NAME             NS_LITERAL_CSTRING("searchplugins")
00065 #define COMPONENTS_DIR_NAME         NS_LITERAL_CSTRING("components")
00066 
00067 //*****************************************************************************
00068 // winEmbedFileLocProvider::Constructor/Destructor
00069 //*****************************************************************************   
00070 
00071 winEmbedFileLocProvider::winEmbedFileLocProvider(const char* productDirName)
00072 {
00073     strncpy(mProductDirName, productDirName, sizeof(mProductDirName) - 1);
00074     mProductDirName[sizeof(mProductDirName) - 1] = '\0';
00075 }
00076 
00077 winEmbedFileLocProvider::~winEmbedFileLocProvider()
00078 {
00079 }
00080 
00081 
00082 //*****************************************************************************
00083 // winEmbedFileLocProvider::nsISupports
00084 //*****************************************************************************   
00085 
00086 NS_IMPL_ISUPPORTS1(winEmbedFileLocProvider, nsIDirectoryServiceProvider)
00087 
00088 //*****************************************************************************
00089 // winEmbedFileLocProvider::nsIDirectoryServiceProvider
00090 //*****************************************************************************   
00091 
00092 NS_IMETHODIMP
00093 winEmbedFileLocProvider::GetFile(const char *prop, PRBool *persistant, nsIFile **_retval)
00094 {    
00095        nsCOMPtr<nsILocalFile>  localFile;
00096        nsresult rv = NS_ERROR_FAILURE;
00097 
00098        *_retval = nsnull;
00099        *persistant = PR_TRUE;
00100        
00101     if (nsCRT::strcmp(prop, NS_APP_APPLICATION_REGISTRY_DIR) == 0)
00102     {
00103         rv = GetProductDirectory(getter_AddRefs(localFile));
00104     }
00105     else if (nsCRT::strcmp(prop, NS_APP_APPLICATION_REGISTRY_FILE) == 0)
00106     {
00107         rv = GetProductDirectory(getter_AddRefs(localFile));
00108         if (NS_SUCCEEDED(rv))
00109             rv = localFile->AppendNative(APP_REGISTRY_NAME);
00110     }
00111     else if (nsCRT::strcmp(prop, NS_APP_DEFAULTS_50_DIR) == 0)
00112     {
00113         rv = CloneMozBinDirectory(getter_AddRefs(localFile));
00114         if (NS_SUCCEEDED(rv))
00115             rv = localFile->AppendRelativeNativePath(DEFAULTS_DIR_NAME);
00116     }
00117     else if (nsCRT::strcmp(prop, NS_APP_PREF_DEFAULTS_50_DIR) == 0)
00118     {
00119         rv = CloneMozBinDirectory(getter_AddRefs(localFile));
00120         if (NS_SUCCEEDED(rv)) {
00121             rv = localFile->AppendRelativeNativePath(DEFAULTS_DIR_NAME);
00122             if (NS_SUCCEEDED(rv))
00123                 rv = localFile->AppendRelativeNativePath(DEFAULTS_PREF_DIR_NAME);
00124         }
00125     }
00126     else if (nsCRT::strcmp(prop, NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR) == 0 ||
00127              nsCRT::strcmp(prop, NS_APP_PROFILE_DEFAULTS_50_DIR) == 0)
00128     {
00129         rv = CloneMozBinDirectory(getter_AddRefs(localFile));
00130         if (NS_SUCCEEDED(rv)) {
00131             rv = localFile->AppendRelativeNativePath(DEFAULTS_DIR_NAME);
00132             if (NS_SUCCEEDED(rv))
00133                 rv = localFile->AppendRelativeNativePath(DEFAULTS_PROFILE_DIR_NAME);
00134         }
00135     }
00136     else if (nsCRT::strcmp(prop, NS_APP_USER_PROFILES_ROOT_DIR) == 0)
00137     {
00138         rv = GetDefaultUserProfileRoot(getter_AddRefs(localFile));   
00139     }
00140     else if (nsCRT::strcmp(prop, NS_APP_RES_DIR) == 0)
00141     {
00142         rv = CloneMozBinDirectory(getter_AddRefs(localFile));
00143         if (NS_SUCCEEDED(rv))
00144             rv = localFile->AppendRelativeNativePath(RES_DIR_NAME);
00145     }
00146     else if (nsCRT::strcmp(prop, NS_APP_CHROME_DIR) == 0)
00147     {
00148         rv = CloneMozBinDirectory(getter_AddRefs(localFile));
00149         if (NS_SUCCEEDED(rv))
00150             rv = localFile->AppendRelativeNativePath(CHROME_DIR_NAME);
00151     }
00152     else if (nsCRT::strcmp(prop, NS_APP_PLUGINS_DIR) == 0)
00153     {
00154         rv = CloneMozBinDirectory(getter_AddRefs(localFile));
00155         if (NS_SUCCEEDED(rv))
00156             rv = localFile->AppendRelativeNativePath(PLUGINS_DIR_NAME);
00157     }
00158     else if (nsCRT::strcmp(prop, NS_APP_SEARCH_DIR) == 0)
00159     {
00160         rv = CloneMozBinDirectory(getter_AddRefs(localFile));
00161         if (NS_SUCCEEDED(rv))
00162             rv = localFile->AppendRelativeNativePath(SEARCH_DIR_NAME);
00163     }
00164     //---------------------------------------------------------------
00165     // Note that by returning a valid localFile's for NS_GRE_DIR and
00166     // NS_GRE_COMPONENT_DIR your app is indicating to XPCOM that 
00167     // it found an GRE version with which it's compatible with and 
00168     // it intends to be "run against" that GRE
00169     //
00170     // Please see http://www.mozilla.org/projects/embedding/MRE.html
00171     // for more info. on GRE
00172     //---------------------------------------------------------------
00173     else if (nsCRT::strcmp(prop, NS_GRE_DIR) == 0)
00174     {
00175         rv = GetGreDirectory(getter_AddRefs(localFile));
00176     }    
00177     else if (nsCRT::strcmp(prop, NS_GRE_COMPONENT_DIR) == 0)
00178     {
00179         rv = GetGreDirectory(getter_AddRefs(localFile));
00180         if (NS_SUCCEEDED(rv))
00181             rv = localFile->AppendRelativeNativePath(COMPONENTS_DIR_NAME);
00182     }    
00183    
00184        if (localFile && NS_SUCCEEDED(rv))
00185               return localFile->QueryInterface(NS_GET_IID(nsIFile), (void**)_retval);
00186               
00187        return rv;
00188 }
00189 
00190 // Get the location of the GRE version we're compatible with from 
00191 // the registry
00192 //
00193 static char * GetGreLocationFromRegistry()
00194 {
00195     char szKey[256];
00196     HKEY hRegKey = NULL;
00197     DWORD dwLength = _MAX_PATH * sizeof(char);
00198     long rc;
00199     char keyValue[_MAX_PATH + 1];
00200     char *pGreLocation = NULL;
00201 
00202     // A couple of key points here:
00203     // 1. Note the usage of the "Software\\Mozilla\\GRE" subkey - this allows
00204     //    us to have multiple versions of GREs on the same machine by having
00205     //    subkeys such as 1.0, 1.1, 2.0 etc. under it.
00206     // 2. In this sample below we're looking for the location of GRE version 1.3
00207     //    i.e. we're compatible with GRE 1.3 and we're trying to find it's install
00208     //    location.
00209     //
00210     // Please see http://www.mozilla.org/projects/embedding/MRE.html for
00211     // more info.
00212     //
00213     strcpy(szKey, "Software\\Mozilla\\GRE\\" MOZILLA_VERSION);
00214 
00215     if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_QUERY_VALUE, &hRegKey) == ERROR_SUCCESS) 
00216     {
00217         if ((rc = ::RegQueryValueEx(hRegKey, "GreHome", NULL, NULL, (BYTE *)keyValue, &dwLength))==ERROR_SUCCESS)
00218         {
00219             pGreLocation = ::strdup(keyValue);
00220             ::RegCloseKey(hRegKey);
00221         }
00222     }
00223 
00224     return pGreLocation;
00225 }
00226 
00227 // Create and return the location of the GRE the application is 
00228 // currently using, if any, via the |aLocalFile| param
00229 //
00230 // If an embedding application is written to use an GRE it determines
00231 // the compatible GRE's location by looking in the Windows registry
00232 // In this case GetGreDirectory() creates a new localFile based on the
00233 // GRE path it just read from the registry
00234 //
00235 // If the embedding application is not using an GRE and is running in
00236 // a "regular" embedding scenario GetGreDirectory() simply returns a
00237 // failure code indicating to the caller to fallback to a non-GRE
00238 // based operation - which is the default mode of operation.
00239 // 
00240 // Please see http://www.mozilla.org/projects/embedding/MRE.html for 
00241 // more information on the Mozilla Runtime Environment(GRE) and for 
00242 // the actual registry key whichs contains the GRE path, if any.
00243 
00244 NS_METHOD winEmbedFileLocProvider::GetGreDirectory(nsILocalFile **aLocalFile)
00245 {
00246     NS_ENSURE_ARG_POINTER(aLocalFile);
00247     nsresult rv = NS_ERROR_FAILURE;
00248 
00249     // Get the path of the GRE which is compatible with our embedding application
00250     // from the registry
00251     //
00252     char *pGreDir = GetGreLocationFromRegistry();
00253     if(pGreDir)
00254     {
00255         nsCOMPtr<nsILocalFile> tempLocal;
00256            rv = NS_NewNativeLocalFile(nsDependentCString(pGreDir), TRUE, getter_AddRefs(tempLocal));
00257 
00258         if (tempLocal)
00259         {
00260            *aLocalFile = tempLocal;
00261            NS_ADDREF(*aLocalFile);
00262            rv = NS_OK;
00263         }
00264 
00265         ::free(pGreDir);
00266     }
00267 
00268     return rv;
00269 }
00270  
00271 NS_METHOD winEmbedFileLocProvider::CloneMozBinDirectory(nsILocalFile **aLocalFile)
00272 {
00273     NS_ENSURE_ARG_POINTER(aLocalFile);
00274     nsresult rv;
00275     
00276     if (!mMozBinDirectory)
00277     {        
00278         // Get the mozilla bin directory
00279         // 1. Check the directory service first for NS_XPCOM_CURRENT_PROCESS_DIR
00280         //    This will be set if a directory was passed to NS_InitXPCOM
00281         // 2. If that doesn't work, set it to be the current process directory
00282         
00283         nsCOMPtr<nsIProperties> directoryService = 
00284                  do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
00285         if (NS_FAILED(rv))
00286             return rv;
00287         
00288         rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(mMozBinDirectory));
00289         if (NS_FAILED(rv)) {
00290             rv = directoryService->Get(NS_OS_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(mMozBinDirectory));
00291             if (NS_FAILED(rv))
00292                 return rv;
00293         }
00294     }
00295     
00296     nsCOMPtr<nsIFile> aFile;
00297     rv = mMozBinDirectory->Clone(getter_AddRefs(aFile));
00298     if (NS_FAILED(rv))
00299         return rv;
00300 
00301     nsCOMPtr<nsILocalFile> lfile = do_QueryInterface (aFile);
00302     if (!lfile)
00303         return NS_ERROR_FAILURE;
00304     
00305     NS_IF_ADDREF(*aLocalFile = lfile);
00306     return NS_OK;
00307 }
00308 
00309 
00310 //----------------------------------------------------------------------------------------
00311 // GetProductDirectory - Gets the directory which contains the application data folder
00312 //
00313 // WIN    : <Application Data folder on user's machine>\Mozilla 
00314 //----------------------------------------------------------------------------------------
00315 NS_METHOD winEmbedFileLocProvider::GetProductDirectory(nsILocalFile **aLocalFile)
00316 {
00317     NS_ENSURE_ARG_POINTER(aLocalFile);
00318     
00319     nsresult rv;
00320     PRBool exists;
00321     nsCOMPtr<nsILocalFile> localDir;
00322    
00323     nsCOMPtr<nsIProperties> directoryService = 
00324              do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
00325     if (NS_FAILED(rv)) return rv;
00326     rv = directoryService->Get(NS_WIN_APPDATA_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(localDir));
00327     if (NS_SUCCEEDED(rv))
00328         rv = localDir->Exists(&exists);
00329     if (NS_FAILED(rv) || !exists)
00330     {
00331         // On some Win95 machines, NS_WIN_APPDATA_DIR does not exist - revert to NS_WIN_WINDOWS_DIR
00332         localDir = nsnull;
00333         rv = directoryService->Get(NS_WIN_WINDOWS_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(localDir));
00334     }
00335     if (NS_FAILED(rv)) return rv;
00336 
00337     rv = localDir->AppendRelativeNativePath(nsDependentCString(mProductDirName));
00338     if (NS_FAILED(rv)) return rv;
00339     rv = localDir->Exists(&exists);
00340     if (NS_SUCCEEDED(rv) && !exists)
00341         rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
00342     if (NS_FAILED(rv)) return rv;
00343 
00344     *aLocalFile = localDir;
00345     NS_ADDREF(*aLocalFile);
00346 
00347    return rv; 
00348 }
00349 
00350 
00351 //----------------------------------------------------------------------------------------
00352 // GetDefaultUserProfileRoot - Gets the directory which contains each user profile dir
00353 //
00354 // WIN    : <Application Data folder on user's machine>\Mozilla\Users50 
00355 //----------------------------------------------------------------------------------------
00356 NS_METHOD winEmbedFileLocProvider::GetDefaultUserProfileRoot(nsILocalFile **aLocalFile)
00357 {
00358     NS_ENSURE_ARG_POINTER(aLocalFile);
00359     
00360     nsresult rv;
00361     PRBool exists;
00362     nsCOMPtr<nsILocalFile> localDir;
00363    
00364     rv = GetProductDirectory(getter_AddRefs(localDir));
00365     if (NS_FAILED(rv)) return rv;
00366 
00367     // These 3 platforms share this part of the path - do them as one
00368     rv = localDir->AppendRelativeNativePath(PROFILE_ROOT_DIR_NAME);
00369     if (NS_FAILED(rv)) return rv;
00370     rv = localDir->Exists(&exists);
00371     if (NS_SUCCEEDED(rv) && !exists)
00372         rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
00373     if (NS_FAILED(rv)) return rv;
00374 
00375     *aLocalFile = localDir;
00376     NS_ADDREF(*aLocalFile);
00377 
00378    return rv; 
00379 }
00380