LCOV - code coverage report
Current view: directory - toolkit/xre - nsXREDirProvider.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 497 66 13.3 %
Date: 2012-06-02 Functions: 38 8 21.1 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       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) 2002
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *  Brian Ryner <bryner@brianryner.com>
      24                 :  *  Benjamin Smedberg <bsmedberg@covad.net>
      25                 :  *  Ben Goodger <ben@mozilla.org>
      26                 :  *  Jens Bannmann <jens.b@web.de>
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      30                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : #include "nsAppRunner.h"
      43                 : #include "nsToolkitCompsCID.h"
      44                 : #include "nsXREDirProvider.h"
      45                 : 
      46                 : #include "jsapi.h"
      47                 : 
      48                 : #include "nsIJSContextStack.h"
      49                 : #include "nsIAppStartup.h"
      50                 : #include "nsIDirectoryEnumerator.h"
      51                 : #include "nsILocalFile.h"
      52                 : #include "nsIObserver.h"
      53                 : #include "nsIObserverService.h"
      54                 : #include "nsIProfileChangeStatus.h"
      55                 : #include "nsISimpleEnumerator.h"
      56                 : #include "nsIToolkitChromeRegistry.h"
      57                 : 
      58                 : #include "nsAppDirectoryServiceDefs.h"
      59                 : #include "nsDirectoryServiceDefs.h"
      60                 : #include "nsDirectoryServiceUtils.h"
      61                 : #include "nsXULAppAPI.h"
      62                 : #include "nsCategoryManagerUtils.h"
      63                 : 
      64                 : #include "nsINIParser.h"
      65                 : #include "nsDependentString.h"
      66                 : #include "nsCOMArray.h"
      67                 : #include "nsArrayEnumerator.h"
      68                 : #include "nsEnumeratorUtils.h"
      69                 : #include "nsReadableUtils.h"
      70                 : #include "mozilla/Services.h"
      71                 : #include "mozilla/Omnijar.h"
      72                 : #include "mozilla/Preferences.h"
      73                 : #include "mozilla/Telemetry.h"
      74                 : 
      75                 : #include <stdlib.h>
      76                 : 
      77                 : #ifdef XP_WIN
      78                 : #include <windows.h>
      79                 : #include <shlobj.h>
      80                 : #endif
      81                 : #ifdef XP_MACOSX
      82                 : #include "nsILocalFileMac.h"
      83                 : #endif
      84                 : #ifdef XP_UNIX
      85                 : #include <ctype.h>
      86                 : #endif
      87                 : #ifdef XP_OS2
      88                 : #define INCL_DOS
      89                 : #include <os2.h>
      90                 : #endif
      91                 : 
      92                 : #if defined(XP_MACOSX)
      93                 : #define APP_REGISTRY_NAME "Application Registry"
      94                 : #elif defined(XP_WIN) || defined(XP_OS2)
      95                 : #define APP_REGISTRY_NAME "registry.dat"
      96                 : #else
      97                 : #define APP_REGISTRY_NAME "appreg"
      98                 : #endif
      99                 : 
     100                 : #define PREF_OVERRIDE_DIRNAME "preferences"
     101                 : 
     102                 : static already_AddRefed<nsILocalFile>
     103               0 : CloneAndAppend(nsIFile* aFile, const char* name)
     104                 : {
     105               0 :   nsCOMPtr<nsIFile> file;
     106               0 :   aFile->Clone(getter_AddRefs(file));
     107               0 :   nsCOMPtr<nsILocalFile> lfile = do_QueryInterface(file);
     108               0 :   lfile->AppendNative(nsDependentCString(name));
     109               0 :   return lfile.forget();
     110                 : }
     111                 : 
     112                 : nsXREDirProvider* gDirServiceProvider = nsnull;
     113                 : 
     114              23 : nsXREDirProvider::nsXREDirProvider() :
     115              23 :   mProfileNotified(false)
     116                 : {
     117              23 :   gDirServiceProvider = this;
     118              23 : }
     119                 : 
     120              46 : nsXREDirProvider::~nsXREDirProvider()
     121                 : {
     122              23 :   gDirServiceProvider = nsnull;
     123              23 : }
     124                 : 
     125                 : nsresult
     126              23 : nsXREDirProvider::Initialize(nsIFile *aXULAppDir,
     127                 :                              nsILocalFile *aGREDir,
     128                 :                              nsIDirectoryServiceProvider* aAppProvider)
     129                 : {
     130              23 :   NS_ENSURE_ARG(aXULAppDir);
     131              23 :   NS_ENSURE_ARG(aGREDir);
     132                 : 
     133              23 :   mAppProvider = aAppProvider;
     134              23 :   mXULAppDir = aXULAppDir;
     135              23 :   mGREDir = aGREDir;
     136                 : 
     137              23 :   if (!mProfileDir) {
     138              46 :     nsCOMPtr<nsIDirectoryServiceProvider> app(do_QueryInterface(mAppProvider));
     139              23 :     if (app) {
     140               0 :       bool per = false;
     141               0 :       app->GetFile(NS_APP_USER_PROFILE_50_DIR, &per, getter_AddRefs(mProfileDir));
     142               0 :       NS_ASSERTION(per, "NS_APP_USER_PROFILE_50_DIR must be persistent!"); 
     143               0 :       NS_ASSERTION(mProfileDir, "NS_APP_USER_PROFILE_50_DIR not defined! This shouldn't happen!"); 
     144                 :     }
     145                 :   }
     146                 : 
     147              23 :   LoadAppBundleDirs();
     148              23 :   return NS_OK;
     149                 : }
     150                 : 
     151                 : nsresult
     152               0 : nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir)
     153                 : {
     154               0 :   NS_ASSERTION(aDir && aLocalDir, "We don't support no-profile apps yet!");
     155                 : 
     156                 :   nsresult rv;
     157                 : 
     158               0 :   rv = EnsureDirectoryExists(aDir);
     159               0 :   if (NS_FAILED(rv))
     160               0 :     return rv;
     161                 : 
     162               0 :   rv = EnsureDirectoryExists(aLocalDir);
     163               0 :   if (NS_FAILED(rv))
     164               0 :     return rv;
     165                 : 
     166               0 :   mProfileDir = aDir;
     167               0 :   mProfileLocalDir = aLocalDir;
     168               0 :   return NS_OK;
     169                 : }
     170                 : 
     171               0 : NS_IMPL_QUERY_INTERFACE3(nsXREDirProvider,
     172                 :                          nsIDirectoryServiceProvider,
     173                 :                          nsIDirectoryServiceProvider2,
     174                 :                          nsIProfileStartup)
     175                 : 
     176                 : NS_IMETHODIMP_(nsrefcnt)
     177               0 : nsXREDirProvider::AddRef()
     178                 : {
     179               0 :   return 1;
     180                 : }
     181                 : 
     182                 : NS_IMETHODIMP_(nsrefcnt)
     183               0 : nsXREDirProvider::Release()
     184                 : {
     185               0 :   return 0;
     186                 : }
     187                 : 
     188                 : NS_IMETHODIMP
     189               0 : nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
     190                 :                           nsIFile** aFile)
     191                 : {
     192                 :   nsresult rv;
     193                 : 
     194               0 :   bool gettingProfile = false;
     195                 : 
     196               0 :   if (!strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR)) {
     197                 :     // If XRE_NotifyProfile hasn't been called, don't fall through to
     198                 :     // mAppProvider on the profile keys.
     199               0 :     if (!mProfileNotified)
     200               0 :       return NS_ERROR_FAILURE;
     201                 : 
     202               0 :     if (mProfileLocalDir)
     203               0 :       return mProfileLocalDir->Clone(aFile);
     204                 : 
     205               0 :     if (mAppProvider)
     206               0 :       return mAppProvider->GetFile(aProperty, aPersistent, aFile);
     207                 : 
     208                 :     // This falls through to the case below
     209               0 :     gettingProfile = true;
     210                 :   }
     211               0 :   if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) || gettingProfile) {
     212               0 :     if (!mProfileNotified)
     213               0 :       return NS_ERROR_FAILURE;
     214                 : 
     215               0 :     if (mProfileDir)
     216               0 :       return mProfileDir->Clone(aFile);
     217                 : 
     218               0 :     if (mAppProvider)
     219               0 :       return mAppProvider->GetFile(aProperty, aPersistent, aFile);
     220                 : 
     221                 :     // If we don't succeed here, bail early so that we aren't reentrant
     222                 :     // through the "GetProfileDir" call below.
     223               0 :     return NS_ERROR_FAILURE;
     224                 :   }
     225                 : 
     226               0 :   if (mAppProvider) {
     227               0 :     rv = mAppProvider->GetFile(aProperty, aPersistent, aFile);
     228               0 :     if (NS_SUCCEEDED(rv) && *aFile)
     229               0 :       return rv;
     230                 :   }
     231                 : 
     232               0 :   *aPersistent = true;
     233                 : 
     234               0 :   if (!strcmp(aProperty, NS_GRE_DIR)) {
     235               0 :     return mGREDir->Clone(aFile);
     236                 :   }
     237               0 :   else if (!strcmp(aProperty, NS_OS_CURRENT_PROCESS_DIR) ||
     238               0 :       !strcmp(aProperty, NS_APP_INSTALL_CLEANUP_DIR)) {
     239               0 :     return GetAppDir()->Clone(aFile);
     240                 :   }
     241                 : 
     242               0 :   rv = NS_ERROR_FAILURE;
     243               0 :   nsCOMPtr<nsIFile> file;
     244                 : 
     245               0 :   if (!strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_50_DIR) ||
     246               0 :            !strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR)) {
     247               0 :     return GetProfileDefaultsDir(aFile);
     248                 :   }
     249               0 :   else if (!strcmp(aProperty, NS_APP_PREF_DEFAULTS_50_DIR))
     250                 :   {
     251                 :     // return the GRE default prefs directory here, and the app default prefs
     252                 :     // directory (if applicable) in NS_APP_PREFS_DEFAULTS_DIR_LIST.
     253               0 :     rv = mGREDir->Clone(getter_AddRefs(file));
     254               0 :     if (NS_SUCCEEDED(rv)) {
     255               0 :       rv = file->AppendNative(NS_LITERAL_CSTRING("defaults"));
     256               0 :       if (NS_SUCCEEDED(rv))
     257               0 :         rv = file->AppendNative(NS_LITERAL_CSTRING("pref"));
     258                 :     }
     259                 :   }
     260               0 :   else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_DIR) ||
     261               0 :            !strcmp(aProperty, XRE_USER_APP_DATA_DIR)) {
     262               0 :     rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file));
     263                 :   }
     264               0 :   else if (!strcmp(aProperty, XRE_UPDATE_ROOT_DIR)) {
     265                 : #if defined(XP_WIN)
     266                 :     rv = GetUpdateRootDir(getter_AddRefs(file));
     267                 : #else
     268                 :     // Only supported on Windows, so just immediately fail.
     269               0 :     return NS_ERROR_FAILURE;
     270                 : #endif
     271                 :   }
     272               0 :   else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_FILE)) {
     273               0 :     rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file));
     274               0 :     if (NS_SUCCEEDED(rv))
     275               0 :       rv = file->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME));
     276                 :   }
     277               0 :   else if (!strcmp(aProperty, NS_APP_USER_PROFILES_ROOT_DIR)) {
     278               0 :     rv = GetUserAppDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file));
     279                 : 
     280               0 :     if (NS_SUCCEEDED(rv)) {
     281                 : #if !defined(XP_UNIX) || defined(XP_MACOSX)
     282                 :       rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
     283                 : #endif
     284                 : 
     285                 :       // We must create the profile directory here if it does not exist.
     286               0 :       rv |= EnsureDirectoryExists(file);
     287                 :     }
     288                 :   }
     289               0 :   else if (!strcmp(aProperty, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR)) {
     290               0 :     rv = GetUserLocalDataDirectory((nsILocalFile**)(nsIFile**) getter_AddRefs(file));
     291                 : 
     292               0 :     if (NS_SUCCEEDED(rv)) {
     293                 : #if !defined(XP_UNIX) || defined(XP_MACOSX)
     294                 :       rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
     295                 : #endif
     296                 : 
     297                 :       // We must create the profile directory here if it does not exist.
     298               0 :       rv |= EnsureDirectoryExists(file);
     299                 :     }
     300                 :   }
     301               0 :   else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) {
     302               0 :     nsCOMPtr<nsILocalFile> lf;
     303               0 :     rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
     304               0 :     if (NS_SUCCEEDED(rv))
     305               0 :       file = lf;
     306                 :   }
     307                 : 
     308               0 :   else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) {
     309               0 :     return mProfileDir->Clone(aFile);
     310                 :   }
     311               0 :   else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
     312               0 :     if (mProfileLocalDir)
     313               0 :       return mProfileLocalDir->Clone(aFile);
     314                 : 
     315               0 :     if (mProfileDir)
     316               0 :       return mProfileDir->Clone(aFile);
     317                 : 
     318               0 :     if (mAppProvider)
     319               0 :       return mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP, aPersistent,
     320               0 :                                    aFile);
     321                 :   }
     322                 : #if defined(XP_UNIX) || defined(XP_MACOSX)
     323               0 :   else if (!strcmp(aProperty, XRE_SYS_LOCAL_EXTENSION_PARENT_DIR)) {
     324                 : #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
     325               0 :     return GetSystemExtensionsDirectory((nsILocalFile**)(nsIFile**) aFile);
     326                 : #else
     327                 :     return NS_ERROR_FAILURE;
     328                 : #endif
     329                 :   }
     330                 : #endif
     331                 : #if defined(XP_UNIX) && !defined(XP_MACOSX)
     332               0 :   else if (!strcmp(aProperty, XRE_SYS_SHARE_EXTENSION_PARENT_DIR)) {
     333                 : #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
     334                 :     static const char *const sysLExtDir = "/usr/share/mozilla/extensions";
     335               0 :     return NS_NewNativeLocalFile(nsDependentCString(sysLExtDir),
     336               0 :                                  false, (nsILocalFile**)(nsIFile**) aFile);
     337                 : #else
     338                 :     return NS_ERROR_FAILURE;
     339                 : #endif
     340                 :   }
     341                 : #endif
     342               0 :   else if (!strcmp(aProperty, XRE_USER_SYS_EXTENSION_DIR)) {
     343                 : #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
     344               0 :     return GetSysUserExtensionsDirectory((nsILocalFile**)(nsIFile**) aFile);
     345                 : #else
     346                 :     return NS_ERROR_FAILURE;
     347                 : #endif
     348                 :   }
     349               0 :   else if (!strcmp(aProperty, XRE_APP_DISTRIBUTION_DIR)) {
     350               0 :     rv = GetAppDir()->Clone(getter_AddRefs(file));
     351               0 :     if (NS_SUCCEEDED(rv))
     352               0 :       rv = file->AppendNative(NS_LITERAL_CSTRING("distribution"));
     353                 :   }
     354               0 :   else if (NS_SUCCEEDED(GetProfileStartupDir(getter_AddRefs(file)))) {
     355                 :     // We need to allow component, xpt, and chrome registration to
     356                 :     // occur prior to the profile-after-change notification.
     357               0 :     if (!strcmp(aProperty, NS_APP_USER_CHROME_DIR)) {
     358               0 :       rv = file->AppendNative(NS_LITERAL_CSTRING("chrome"));
     359                 :     }
     360                 :   }
     361                 : 
     362               0 :   if (NS_SUCCEEDED(rv) && file) {
     363               0 :     NS_ADDREF(*aFile = file);
     364               0 :     return NS_OK;
     365                 :   }
     366                 : 
     367               0 :   bool ensureFilePermissions = false;
     368                 : 
     369               0 :   if (NS_SUCCEEDED(GetProfileDir(getter_AddRefs(file)))) {
     370               0 :     if (!strcmp(aProperty, NS_APP_PREFS_50_DIR)) {
     371               0 :       rv = NS_OK;
     372                 :     }
     373               0 :     else if (!strcmp(aProperty, NS_APP_PREFS_50_FILE)) {
     374               0 :       rv = file->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
     375                 :     }
     376               0 :     else if (!strcmp(aProperty, NS_LOCALSTORE_UNSAFE_FILE)) {
     377               0 :       rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
     378                 :     }
     379               0 :     else if (!strcmp(aProperty, NS_APP_LOCALSTORE_50_FILE)) {
     380               0 :       if (gSafeMode) {
     381               0 :         rv = file->AppendNative(NS_LITERAL_CSTRING("localstore-safe.rdf"));
     382               0 :         file->Remove(false);
     383                 :       }
     384                 :       else {
     385               0 :         rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
     386               0 :         EnsureProfileFileExists(file);
     387               0 :         ensureFilePermissions = true;
     388                 :       }
     389                 :     }
     390               0 :     else if (!strcmp(aProperty, NS_APP_USER_MIMETYPES_50_FILE)) {
     391               0 :       rv = file->AppendNative(NS_LITERAL_CSTRING("mimeTypes.rdf"));
     392               0 :       EnsureProfileFileExists(file);
     393               0 :       ensureFilePermissions = true;
     394                 :     }
     395               0 :     else if (!strcmp(aProperty, NS_APP_STORAGE_50_FILE)) {
     396               0 :       rv = file->AppendNative(NS_LITERAL_CSTRING("storage.sdb"));
     397                 :     }
     398               0 :     else if (!strcmp(aProperty, NS_APP_DOWNLOADS_50_FILE)) {
     399               0 :       rv = file->AppendNative(NS_LITERAL_CSTRING("downloads.rdf"));
     400                 :     }
     401               0 :     else if (!strcmp(aProperty, NS_APP_PREFS_OVERRIDE_DIR)) {
     402               0 :       rv = mProfileDir->Clone(getter_AddRefs(file));
     403               0 :       rv |= file->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));
     404               0 :       rv |= EnsureDirectoryExists(file);
     405                 :     }
     406                 :   }
     407               0 :   if (NS_FAILED(rv) || !file)
     408               0 :     return NS_ERROR_FAILURE;
     409                 : 
     410               0 :   if (ensureFilePermissions) {
     411                 :     bool fileToEnsureExists;
     412                 :     bool isWritable;
     413               0 :     if (NS_SUCCEEDED(file->Exists(&fileToEnsureExists)) && fileToEnsureExists
     414               0 :         && NS_SUCCEEDED(file->IsWritable(&isWritable)) && !isWritable) {
     415                 :       PRUint32 permissions;
     416               0 :       if (NS_SUCCEEDED(file->GetPermissions(&permissions))) {
     417               0 :         rv = file->SetPermissions(permissions | 0600);
     418               0 :         NS_ASSERTION(NS_SUCCEEDED(rv), "failed to ensure file permissions");
     419                 :       }
     420                 :     }
     421                 :   }
     422                 : 
     423               0 :   NS_ADDREF(*aFile = file);
     424               0 :   return NS_OK;
     425                 : }
     426                 : 
     427                 : static void
     428               0 : LoadAppDirIntoArray(nsIFile* aXULAppDir,
     429                 :                     const char *const *aAppendList,
     430                 :                     nsCOMArray<nsIFile>& aDirectories)
     431                 : {
     432               0 :   if (!aXULAppDir)
     433               0 :     return;
     434                 : 
     435               0 :   nsCOMPtr<nsIFile> subdir;
     436               0 :   aXULAppDir->Clone(getter_AddRefs(subdir));
     437               0 :   if (!subdir)
     438                 :     return;
     439                 : 
     440               0 :   for (; *aAppendList; ++aAppendList)
     441               0 :     subdir->AppendNative(nsDependentCString(*aAppendList));
     442                 : 
     443                 :   bool exists;
     444               0 :   if (NS_SUCCEEDED(subdir->Exists(&exists)) && exists)
     445               0 :     aDirectories.AppendObject(subdir);
     446                 : }
     447                 : 
     448                 : static void
     449               0 : LoadDirsIntoArray(nsCOMArray<nsIFile>& aSourceDirs,
     450                 :                   const char *const* aAppendList,
     451                 :                   nsCOMArray<nsIFile>& aDirectories)
     452                 : {
     453               0 :   nsCOMPtr<nsIFile> appended;
     454                 :   bool exists;
     455                 : 
     456               0 :   for (PRInt32 i = 0; i < aSourceDirs.Count(); ++i) {
     457               0 :     aSourceDirs[i]->Clone(getter_AddRefs(appended));
     458               0 :     if (!appended)
     459               0 :       continue;
     460                 : 
     461               0 :     nsCAutoString leaf;
     462               0 :     appended->GetNativeLeafName(leaf);
     463               0 :     if (!Substring(leaf, leaf.Length() - 4).Equals(NS_LITERAL_CSTRING(".xpi"))) {
     464               0 :       for (const char *const *a = aAppendList; *a; ++a)
     465               0 :         appended->AppendNative(nsDependentCString(*a));
     466                 :     }
     467                 : 
     468               0 :     if (NS_SUCCEEDED(appended->Exists(&exists)) && exists)
     469               0 :       aDirectories.AppendObject(appended);
     470                 :   }
     471               0 : }
     472                 : 
     473                 : NS_IMETHODIMP
     474               0 : nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult)
     475                 : {
     476                 :   nsresult rv;
     477                 : 
     478               0 :   nsCOMPtr<nsISimpleEnumerator> appEnum;
     479                 :   nsCOMPtr<nsIDirectoryServiceProvider2>
     480               0 :     appP2(do_QueryInterface(mAppProvider));
     481               0 :   if (appP2) {
     482               0 :     rv = appP2->GetFiles(aProperty, getter_AddRefs(appEnum));
     483               0 :     if (NS_FAILED(rv)) {
     484               0 :       appEnum = nsnull;
     485                 :     }
     486               0 :     else if (rv != NS_SUCCESS_AGGREGATE_RESULT) {
     487               0 :       NS_ADDREF(*aResult = appEnum);
     488               0 :       return NS_OK;
     489                 :     }
     490                 :   }
     491                 : 
     492               0 :   nsCOMPtr<nsISimpleEnumerator> xreEnum;
     493               0 :   rv = GetFilesInternal(aProperty, getter_AddRefs(xreEnum));
     494               0 :   if (NS_FAILED(rv)) {
     495               0 :     if (appEnum) {
     496               0 :       NS_ADDREF(*aResult = appEnum);
     497               0 :       return NS_SUCCESS_AGGREGATE_RESULT;
     498                 :     }
     499                 : 
     500               0 :     return rv;
     501                 :   }
     502                 : 
     503               0 :   rv = NS_NewUnionEnumerator(aResult, appEnum, xreEnum);
     504               0 :   if (NS_FAILED(rv))
     505               0 :     return rv;
     506                 : 
     507               0 :   return NS_SUCCESS_AGGREGATE_RESULT;
     508                 : }
     509                 : 
     510                 : static void
     511               0 : LoadExtensionDirectories(nsINIParser &parser,
     512                 :                          const char *aSection,
     513                 :                          nsCOMArray<nsIFile> &aDirectories,
     514                 :                          NSLocationType aType)
     515                 : {
     516                 :   nsresult rv;
     517               0 :   PRInt32 i = 0;
     518               0 :   do {
     519               0 :     nsCAutoString buf("Extension");
     520               0 :     buf.AppendInt(i++);
     521                 : 
     522               0 :     nsCAutoString path;
     523               0 :     rv = parser.GetString(aSection, buf.get(), path);
     524               0 :     if (NS_FAILED(rv))
     525                 :       return;
     526                 : 
     527               0 :     nsCOMPtr<nsILocalFile> dir = do_CreateInstance("@mozilla.org/file/local;1", &rv);
     528               0 :     if (NS_FAILED(rv))
     529               0 :       continue;
     530                 : 
     531               0 :     rv = dir->SetPersistentDescriptor(path);
     532               0 :     if (NS_FAILED(rv))
     533               0 :       continue;
     534                 : 
     535               0 :     aDirectories.AppendObject(dir);
     536               0 :     if (Substring(path, path.Length() - 4).Equals(NS_LITERAL_CSTRING(".xpi"))) {
     537               0 :       XRE_AddJarManifestLocation(aType, dir);
     538                 :     }
     539                 :     else {
     540                 :       nsCOMPtr<nsILocalFile> manifest =
     541               0 :         CloneAndAppend(dir, "chrome.manifest");
     542               0 :       XRE_AddManifestLocation(aType, manifest);
     543                 :     }
     544                 :   }
     545                 :   while (true);
     546                 : }
     547                 : 
     548                 : void
     549               0 : nsXREDirProvider::LoadExtensionBundleDirectories()
     550                 : {
     551               0 :   if (mProfileDir && !gSafeMode) {
     552               0 :     nsCOMPtr<nsIFile> extensionsINI;
     553               0 :     mProfileDir->Clone(getter_AddRefs(extensionsINI));
     554               0 :     if (!extensionsINI)
     555                 :       return;
     556                 : 
     557               0 :     extensionsINI->AppendNative(NS_LITERAL_CSTRING("extensions.ini"));
     558                 : 
     559                 :     nsCOMPtr<nsILocalFile> extensionsINILF =
     560               0 :       do_QueryInterface(extensionsINI);
     561               0 :     if (!extensionsINILF)
     562                 :       return;
     563                 : 
     564               0 :     nsINIParser parser;
     565               0 :     nsresult rv = parser.Init(extensionsINILF);
     566               0 :     if (NS_FAILED(rv))
     567                 :       return;
     568                 : 
     569                 :     LoadExtensionDirectories(parser, "ExtensionDirs", mExtensionDirectories,
     570               0 :                              NS_COMPONENT_LOCATION);
     571                 :     LoadExtensionDirectories(parser, "ThemeDirs", mThemeDirectories,
     572               0 :                              NS_SKIN_LOCATION);
     573                 :   }
     574                 : }
     575                 : 
     576                 : void
     577              23 : nsXREDirProvider::LoadAppBundleDirs()
     578                 : {
     579              46 :   nsCOMPtr<nsIFile> dir;
     580              23 :   nsresult rv = mXULAppDir->Clone(getter_AddRefs(dir));
     581              23 :   if (NS_FAILED(rv))
     582                 :     return;
     583                 : 
     584              23 :   dir->AppendNative(NS_LITERAL_CSTRING("distribution"));
     585              23 :   dir->AppendNative(NS_LITERAL_CSTRING("bundles"));
     586                 : 
     587              46 :   nsCOMPtr<nsISimpleEnumerator> e;
     588              23 :   rv = dir->GetDirectoryEntries(getter_AddRefs(e));
     589              23 :   if (NS_FAILED(rv))
     590                 :     return;
     591                 : 
     592               0 :   nsCOMPtr<nsIDirectoryEnumerator> files = do_QueryInterface(e);
     593               0 :   if (!files)
     594                 :     return;
     595                 : 
     596               0 :   nsCOMPtr<nsIFile> subdir;
     597               0 :   while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(subdir))) && subdir) {
     598               0 :     mAppBundleDirectories.AppendObject(subdir);
     599                 : 
     600                 :     nsCOMPtr<nsILocalFile> manifest =
     601               0 :       CloneAndAppend(subdir, "chrome.manifest");
     602               0 :     XRE_AddManifestLocation(NS_COMPONENT_LOCATION, manifest);
     603                 :   }
     604                 : }
     605                 : 
     606                 : static const char *const kAppendPrefDir[] = { "defaults", "preferences", nsnull };
     607                 : 
     608                 : #ifdef DEBUG_bsmedberg
     609                 : static void
     610                 : DumpFileArray(const char *key,
     611                 :               nsCOMArray<nsIFile> dirs)
     612                 : {
     613                 :   fprintf(stderr, "nsXREDirProvider::GetFilesInternal(%s)\n", key);
     614                 : 
     615                 :   nsCAutoString path;
     616                 :   for (PRInt32 i = 0; i < dirs.Count(); ++i) {
     617                 :     dirs[i]->GetNativePath(path);
     618                 :     fprintf(stderr, "  %s\n", path.get());
     619                 :   }
     620                 : }
     621                 : #endif // DEBUG_bsmedberg
     622                 : 
     623                 : nsresult
     624               0 : nsXREDirProvider::GetFilesInternal(const char* aProperty,
     625                 :                                    nsISimpleEnumerator** aResult)
     626                 : {
     627               0 :   nsresult rv = NS_OK;
     628               0 :   *aResult = nsnull;
     629                 : 
     630               0 :   if (!strcmp(aProperty, XRE_EXTENSIONS_DIR_LIST)) {
     631               0 :     nsCOMArray<nsIFile> directories;
     632                 : 
     633                 :     static const char *const kAppendNothing[] = { nsnull };
     634                 : 
     635                 :     LoadDirsIntoArray(mAppBundleDirectories,
     636               0 :                       kAppendNothing, directories);
     637                 :     LoadDirsIntoArray(mExtensionDirectories,
     638               0 :                       kAppendNothing, directories);
     639                 : 
     640               0 :     rv = NS_NewArrayEnumerator(aResult, directories);
     641                 :   }
     642               0 :   else if (!strcmp(aProperty, NS_APP_PREFS_DEFAULTS_DIR_LIST)) {
     643               0 :     nsCOMArray<nsIFile> directories;
     644                 : 
     645               0 :     LoadAppDirIntoArray(mXULAppDir, kAppendPrefDir, directories);
     646                 :     LoadDirsIntoArray(mAppBundleDirectories,
     647               0 :                       kAppendPrefDir, directories);
     648                 : 
     649               0 :     rv = NS_NewArrayEnumerator(aResult, directories);
     650                 :   }
     651               0 :   else if (!strcmp(aProperty, NS_EXT_PREFS_DEFAULTS_DIR_LIST)) {
     652               0 :     nsCOMArray<nsIFile> directories;
     653                 : 
     654                 :     LoadDirsIntoArray(mExtensionDirectories,
     655               0 :                       kAppendPrefDir, directories);
     656                 : 
     657               0 :     if (mProfileDir) {
     658               0 :       nsCOMPtr<nsIFile> overrideFile;
     659               0 :       mProfileDir->Clone(getter_AddRefs(overrideFile));
     660               0 :       overrideFile->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));
     661                 : 
     662                 :       bool exists;
     663               0 :       if (NS_SUCCEEDED(overrideFile->Exists(&exists)) && exists)
     664               0 :         directories.AppendObject(overrideFile);
     665                 :     }
     666                 : 
     667               0 :     rv = NS_NewArrayEnumerator(aResult, directories);
     668                 :   }
     669               0 :   else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) {
     670                 :     // NS_APP_CHROME_DIR_LIST is only used to get default (native) icons
     671                 :     // for OS window decoration.
     672                 : 
     673                 :     static const char *const kAppendChromeDir[] = { "chrome", nsnull };
     674               0 :     nsCOMArray<nsIFile> directories;
     675                 :     LoadAppDirIntoArray(mXULAppDir,
     676                 :                         kAppendChromeDir,
     677               0 :                         directories);
     678                 :     LoadDirsIntoArray(mAppBundleDirectories,
     679                 :                       kAppendChromeDir,
     680               0 :                       directories);
     681                 :     LoadDirsIntoArray(mExtensionDirectories,
     682                 :                       kAppendChromeDir,
     683               0 :                       directories);
     684                 : 
     685               0 :     rv = NS_NewArrayEnumerator(aResult, directories);
     686                 :   }
     687               0 :   else if (!strcmp(aProperty, NS_APP_PLUGINS_DIR_LIST)) {
     688                 :     static const char *const kAppendPlugins[] = { "plugins", nsnull };
     689               0 :     nsCOMArray<nsIFile> directories;
     690                 : 
     691                 :     // The root dirserviceprovider does quite a bit for us: we're mainly
     692                 :     // interested in xulapp and extension-provided plugins.
     693                 :     LoadDirsIntoArray(mAppBundleDirectories,
     694                 :                       kAppendPlugins,
     695               0 :                       directories);
     696                 :     LoadDirsIntoArray(mExtensionDirectories,
     697                 :                       kAppendPlugins,
     698               0 :                       directories);
     699                 : 
     700               0 :     if (mProfileDir) {
     701               0 :       nsCOMArray<nsIFile> profileDir;
     702               0 :       profileDir.AppendObject(mProfileDir);
     703                 :       LoadDirsIntoArray(profileDir,
     704                 :                         kAppendPlugins,
     705               0 :                         directories);
     706                 :     }
     707                 : 
     708               0 :     rv = NS_NewArrayEnumerator(aResult, directories);
     709               0 :     NS_ENSURE_SUCCESS(rv, rv);
     710                 : 
     711               0 :     rv = NS_SUCCESS_AGGREGATE_RESULT;
     712                 :   }
     713                 :   else
     714               0 :     rv = NS_ERROR_FAILURE;
     715                 : 
     716               0 :   return rv;
     717                 : }
     718                 : 
     719                 : NS_IMETHODIMP
     720               0 : nsXREDirProvider::GetDirectory(nsIFile* *aResult)
     721                 : {
     722               0 :   NS_ENSURE_TRUE(mProfileDir, NS_ERROR_NOT_INITIALIZED);
     723                 : 
     724               0 :   return mProfileDir->Clone(aResult);
     725                 : }
     726                 : 
     727                 : NS_IMETHODIMP
     728               0 : nsXREDirProvider::DoStartup()
     729                 : {
     730               0 :   if (!mProfileNotified) {
     731                 :     nsCOMPtr<nsIObserverService> obsSvc =
     732               0 :       mozilla::services::GetObserverService();
     733               0 :     if (!obsSvc) return NS_ERROR_FAILURE;
     734                 : 
     735               0 :     mProfileNotified = true;
     736                 : 
     737                 :     /*
     738                 :        Setup prefs before profile-do-change to be able to use them to track
     739                 :        crashes and because we want to begin crash tracking before other code run
     740                 :        from this notification since they may cause crashes.
     741                 :     */
     742               0 :     nsresult rv = mozilla::Preferences::ResetAndReadUserPrefs();
     743               0 :     if (NS_FAILED(rv)) NS_WARNING("Failed to setup pref service.");
     744                 : 
     745               0 :     bool safeModeNecessary = false;
     746               0 :     nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
     747               0 :     if (appStartup) {
     748               0 :       rv = appStartup->TrackStartupCrashBegin(&safeModeNecessary);
     749               0 :       if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE)
     750               0 :         NS_WARNING("Error while beginning startup crash tracking");
     751                 : 
     752               0 :       if (!gSafeMode && safeModeNecessary) {
     753               0 :         appStartup->RestartInSafeMode(nsIAppStartup::eForceQuit);
     754               0 :         return NS_OK;
     755                 :       }
     756                 :     }
     757                 : 
     758                 :     static const PRUnichar kStartup[] = {'s','t','a','r','t','u','p','\0'};
     759               0 :     obsSvc->NotifyObservers(nsnull, "profile-do-change", kStartup);
     760                 :     // Init the Extension Manager
     761               0 :     nsCOMPtr<nsIObserver> em = do_GetService("@mozilla.org/addons/integration;1");
     762               0 :     if (em) {
     763               0 :       em->Observe(nsnull, "addons-startup", nsnull);
     764                 :     } else {
     765               0 :       NS_WARNING("Failed to create Addons Manager.");
     766                 :     }
     767                 : 
     768               0 :     LoadExtensionBundleDirectories();
     769                 : 
     770               0 :     obsSvc->NotifyObservers(nsnull, "load-extension-defaults", nsnull);
     771               0 :     obsSvc->NotifyObservers(nsnull, "profile-after-change", kStartup);
     772                 : 
     773                 :     // Any component that has registered for the profile-after-change category
     774                 :     // should also be created at this time.
     775                 :     (void)NS_CreateServicesFromCategory("profile-after-change", nsnull,
     776               0 :                                         "profile-after-change");
     777                 : 
     778               0 :     if (gSafeMode && safeModeNecessary) {
     779                 :       static const PRUnichar kCrashed[] = {'c','r','a','s','h','e','d','\0'};
     780               0 :       obsSvc->NotifyObservers(nsnull, "safemode-forced", kCrashed);
     781                 :     }
     782                 : 
     783                 :     // 1 = Regular mode, 2 = Safe mode, 3 = Safe mode forced
     784               0 :     int mode = 1;
     785               0 :     if (gSafeMode) {
     786               0 :       if (safeModeNecessary)
     787               0 :         mode = 3;
     788                 :       else
     789               0 :         mode = 2;
     790                 :     }
     791               0 :     mozilla::Telemetry::Accumulate(mozilla::Telemetry::SAFE_MODE_USAGE, mode);
     792                 : 
     793               0 :     obsSvc->NotifyObservers(nsnull, "profile-initial-state", nsnull);
     794                 :   }
     795               0 :   return NS_OK;
     796                 : }
     797                 : 
     798                 : class ProfileChangeStatusImpl : public nsIProfileChangeStatus
     799                 : {
     800                 : public:
     801                 :   NS_DECL_ISUPPORTS
     802                 :   NS_DECL_NSIPROFILECHANGESTATUS
     803               0 :   ProfileChangeStatusImpl() { }
     804                 : private:
     805               0 :   ~ProfileChangeStatusImpl() { }
     806                 : };
     807                 : 
     808               0 : NS_IMPL_ISUPPORTS1(ProfileChangeStatusImpl, nsIProfileChangeStatus)
     809                 : 
     810                 : NS_IMETHODIMP
     811               0 : ProfileChangeStatusImpl::VetoChange()
     812                 : {
     813               0 :   NS_ERROR("Can't veto change!");
     814               0 :   return NS_ERROR_FAILURE;
     815                 : }
     816                 : 
     817                 : NS_IMETHODIMP
     818               0 : ProfileChangeStatusImpl::ChangeFailed()
     819                 : {
     820               0 :   NS_ERROR("Profile change cancellation.");
     821               0 :   return NS_ERROR_FAILURE;
     822                 : }
     823                 : 
     824                 : void
     825               0 : nsXREDirProvider::DoShutdown()
     826                 : {
     827               0 :   if (mProfileNotified) {
     828                 :     nsCOMPtr<nsIObserverService> obsSvc =
     829               0 :       mozilla::services::GetObserverService();
     830               0 :     NS_ASSERTION(obsSvc, "No observer service?");
     831               0 :     if (obsSvc) {
     832               0 :       nsCOMPtr<nsIProfileChangeStatus> cs = new ProfileChangeStatusImpl();
     833                 :       static const PRUnichar kShutdownPersist[] =
     834                 :         {'s','h','u','t','d','o','w','n','-','p','e','r','s','i','s','t','\0'};
     835               0 :       obsSvc->NotifyObservers(cs, "profile-change-net-teardown", kShutdownPersist);
     836               0 :       obsSvc->NotifyObservers(cs, "profile-change-teardown", kShutdownPersist);
     837                 : 
     838                 :       // Phase 2c: Now that things are torn down, force JS GC so that things which depend on
     839                 :       // resources which are about to go away in "profile-before-change" are destroyed first.
     840                 :       nsCOMPtr<nsIThreadJSContextStack> stack
     841               0 :         (do_GetService("@mozilla.org/js/xpc/ContextStack;1"));
     842               0 :       if (stack)
     843                 :       {
     844               0 :         JSContext *cx = nsnull;
     845               0 :         stack->GetSafeJSContext(&cx);
     846               0 :         if (cx)
     847               0 :           ::JS_GC(cx);
     848                 :       }
     849                 : 
     850                 :       // Phase 3: Notify observers of a profile change
     851               0 :       obsSvc->NotifyObservers(cs, "profile-before-change", kShutdownPersist);
     852                 :     }
     853               0 :     mProfileNotified = false;
     854                 :   }
     855               0 : }
     856                 : 
     857                 : #ifdef XP_WIN
     858                 : static nsresult
     859                 : GetShellFolderPath(int folder, nsAString& _retval)
     860                 : {
     861                 :   PRUnichar* buf;
     862                 :   PRUint32 bufLength = _retval.GetMutableData(&buf, MAXPATHLEN + 3);
     863                 :   NS_ENSURE_TRUE(bufLength >= (MAXPATHLEN + 3), NS_ERROR_OUT_OF_MEMORY);
     864                 : 
     865                 :   nsresult rv = NS_OK;
     866                 : 
     867                 :   LPITEMIDLIST pItemIDList = NULL;
     868                 : 
     869                 :   if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, folder, &pItemIDList)) &&
     870                 :       SHGetPathFromIDListW(pItemIDList, buf)) {
     871                 :     // We're going to use wcslen (wcsnlen not available in msvc7.1) so make
     872                 :     // sure to null terminate.
     873                 :     buf[bufLength - 1] = L'\0';
     874                 :     _retval.SetLength(wcslen(buf));
     875                 :   } else {
     876                 :     _retval.SetLength(0);
     877                 :     rv = NS_ERROR_NOT_AVAILABLE;
     878                 :   }
     879                 : 
     880                 :   CoTaskMemFree(pItemIDList);
     881                 : 
     882                 :   return rv;
     883                 : }
     884                 : 
     885                 : /**
     886                 :  * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
     887                 :  * querying the registry when the call to SHGetSpecialFolderLocation or
     888                 :  * SHGetPathFromIDListW is unable to provide these paths (Bug 513958).
     889                 :  */
     890                 : static nsresult
     891                 : GetRegWindowsAppDataFolder(bool aLocal, nsAString& _retval)
     892                 : {
     893                 :   HKEY key;
     894                 :   NS_NAMED_LITERAL_STRING(keyName,
     895                 :   "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
     896                 :   DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName.get(), 0, KEY_READ,
     897                 :                               &key);
     898                 :   if (res != ERROR_SUCCESS) {
     899                 :     _retval.SetLength(0);
     900                 :     return NS_ERROR_NOT_AVAILABLE;
     901                 :   }
     902                 : 
     903                 :   DWORD type, size;
     904                 :   res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"), NULL,
     905                 :                          &type, NULL, &size);
     906                 :   // The call to RegQueryValueExW must succeed, the type must be REG_SZ, the
     907                 :   // buffer size must not equal 0, and the buffer size be a multiple of 2.
     908                 :   if (res != ERROR_SUCCESS || type != REG_SZ || size == 0 || size % 2 != 0) {
     909                 :     ::RegCloseKey(key);
     910                 :     _retval.SetLength(0);
     911                 :     return NS_ERROR_NOT_AVAILABLE;
     912                 :   }
     913                 : 
     914                 :   // |size| includes room for the terminating null character
     915                 :   DWORD resultLen = size / 2 - 1;
     916                 : 
     917                 :   _retval.SetLength(resultLen);
     918                 :   nsAString::iterator begin;
     919                 :   _retval.BeginWriting(begin);
     920                 :   if (begin.size_forward() != resultLen) {
     921                 :     ::RegCloseKey(key);
     922                 :     _retval.SetLength(0);
     923                 :     return NS_ERROR_NOT_AVAILABLE;
     924                 :   }
     925                 : 
     926                 :   res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"), NULL,
     927                 :                          NULL, (LPBYTE) begin.get(), &size);
     928                 :   ::RegCloseKey(key);
     929                 :   if (res != ERROR_SUCCESS) {
     930                 :     _retval.SetLength(0);
     931                 :     return NS_ERROR_NOT_AVAILABLE;
     932                 :   }
     933                 : 
     934                 :   return NS_OK;
     935                 : }
     936                 : 
     937                 : nsresult
     938                 : nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult)
     939                 : {
     940                 :   nsCOMPtr<nsIFile> appDir = GetAppDir();
     941                 : 
     942                 :   nsAutoString appPath;
     943                 :   nsresult rv = appDir->GetPath(appPath);
     944                 :   NS_ENSURE_SUCCESS(rv, rv);
     945                 : 
     946                 :   // AppDir may be a short path. Convert to long path to make sure
     947                 :   // the consistency of the update folder location
     948                 :   nsString longPath;
     949                 :   PRUnichar* buf;
     950                 : 
     951                 :   PRUint32 bufLength = longPath.GetMutableData(&buf, MAXPATHLEN);
     952                 :   NS_ENSURE_TRUE(bufLength >= MAXPATHLEN, NS_ERROR_OUT_OF_MEMORY);
     953                 : 
     954                 :   DWORD len = GetLongPathNameW(appPath.get(), buf, bufLength);
     955                 : 
     956                 :   // Failing GetLongPathName() is not fatal.
     957                 :   if (len <= 0 || len >= bufLength)
     958                 :     longPath.Assign(appPath);
     959                 :   else
     960                 :     longPath.SetLength(len);
     961                 : 
     962                 :   // Use <UserLocalDataDir>\updates\<relative path to app dir from
     963                 :   // Program Files> if app dir is under Program Files to avoid the
     964                 :   // folder virtualization mess on Windows Vista
     965                 :   nsAutoString programFiles;
     966                 :   rv = GetShellFolderPath(CSIDL_PROGRAM_FILES, programFiles);
     967                 :   NS_ENSURE_SUCCESS(rv, rv);
     968                 : 
     969                 :   programFiles.AppendLiteral("\\");
     970                 :   PRUint32 programFilesLen = programFiles.Length();
     971                 : 
     972                 :   if (longPath.Length() < programFilesLen)
     973                 :     return NS_ERROR_FAILURE;
     974                 : 
     975                 :   if (_wcsnicmp(programFiles.get(), longPath.get(), programFilesLen) != 0)
     976                 :     return NS_ERROR_FAILURE;
     977                 : 
     978                 :   nsCOMPtr<nsILocalFile> updRoot;
     979                 :   rv = GetUserLocalDataDirectory(getter_AddRefs(updRoot));
     980                 :   NS_ENSURE_SUCCESS(rv, rv);
     981                 : 
     982                 :   rv = updRoot->AppendRelativePath(Substring(longPath, programFilesLen));
     983                 :   NS_ENSURE_SUCCESS(rv, rv);
     984                 : 
     985                 :   NS_ADDREF(*aResult = updRoot);
     986                 :   return NS_OK;
     987                 : }
     988                 : #endif
     989                 : 
     990                 : nsresult
     991               0 : nsXREDirProvider::GetProfileStartupDir(nsIFile* *aResult)
     992                 : {
     993               0 :   if (mProfileDir)
     994               0 :     return mProfileDir->Clone(aResult);
     995                 : 
     996               0 :   if (mAppProvider) {
     997               0 :     nsCOMPtr<nsIFile> needsclone;
     998                 :     bool dummy;
     999               0 :     nsresult rv = mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP,
    1000                 :                                         &dummy,
    1001               0 :                                         getter_AddRefs(needsclone));
    1002               0 :     if (NS_SUCCEEDED(rv))
    1003               0 :       return needsclone->Clone(aResult);
    1004                 :   }
    1005                 : 
    1006               0 :   return NS_ERROR_FAILURE;
    1007                 : }
    1008                 : 
    1009                 : nsresult
    1010               0 : nsXREDirProvider::GetProfileDir(nsIFile* *aResult)
    1011                 : {
    1012               0 :   if (mProfileDir) {
    1013               0 :     if (!mProfileNotified)
    1014               0 :       return NS_ERROR_FAILURE;
    1015                 : 
    1016               0 :     return mProfileDir->Clone(aResult);
    1017                 :   }
    1018                 : 
    1019               0 :   if (mAppProvider) {
    1020               0 :     nsCOMPtr<nsIFile> needsclone;
    1021                 :     bool dummy;
    1022               0 :     nsresult rv = mAppProvider->GetFile(NS_APP_USER_PROFILE_50_DIR,
    1023                 :                                         &dummy,
    1024               0 :                                         getter_AddRefs(needsclone));
    1025               0 :     if (NS_SUCCEEDED(rv))
    1026               0 :       return needsclone->Clone(aResult);
    1027                 :   }
    1028                 : 
    1029               0 :   return NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, aResult);
    1030                 : }
    1031                 : 
    1032                 : nsresult
    1033              22 : nsXREDirProvider::GetUserDataDirectoryHome(nsILocalFile** aFile, bool aLocal)
    1034                 : {
    1035                 :   // Copied from nsAppFileLocationProvider (more or less)
    1036                 :   nsresult rv;
    1037              44 :   nsCOMPtr<nsILocalFile> localDir;
    1038                 : 
    1039                 : #if defined(XP_MACOSX)
    1040                 :   FSRef fsRef;
    1041                 :   OSType folderType;
    1042                 :   if (aLocal) {
    1043                 :     folderType = kCachedDataFolderType;
    1044                 :   } else {
    1045                 : #ifdef MOZ_THUNDERBIRD
    1046                 :     folderType = kDomainLibraryFolderType;
    1047                 : #else
    1048                 :     folderType = kApplicationSupportFolderType;
    1049                 : #endif
    1050                 :   }
    1051                 :   OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef);
    1052                 :   NS_ENSURE_FALSE(err, NS_ERROR_FAILURE);
    1053                 : 
    1054                 :   rv = NS_NewNativeLocalFile(EmptyCString(), true, getter_AddRefs(localDir));
    1055                 :   NS_ENSURE_SUCCESS(rv, rv);
    1056                 : 
    1057                 :   nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(localDir);
    1058                 :   NS_ENSURE_TRUE(dirFileMac, NS_ERROR_UNEXPECTED);
    1059                 : 
    1060                 :   rv = dirFileMac->InitWithFSRef(&fsRef);
    1061                 :   NS_ENSURE_SUCCESS(rv, rv);
    1062                 : 
    1063                 :   localDir = do_QueryInterface(dirFileMac, &rv);
    1064                 : #elif defined(XP_WIN)
    1065                 :   nsString path;
    1066                 :   if (aLocal) {
    1067                 :     rv = GetShellFolderPath(CSIDL_LOCAL_APPDATA, path);
    1068                 :     if (NS_FAILED(rv))
    1069                 :       rv = GetRegWindowsAppDataFolder(aLocal, path);
    1070                 :   }
    1071                 :   if (!aLocal || NS_FAILED(rv)) {
    1072                 :     rv = GetShellFolderPath(CSIDL_APPDATA, path);
    1073                 :     if (NS_FAILED(rv)) {
    1074                 :       if (!aLocal)
    1075                 :         rv = GetRegWindowsAppDataFolder(aLocal, path);
    1076                 :     }
    1077                 :   }
    1078                 :   NS_ENSURE_SUCCESS(rv, rv);
    1079                 : 
    1080                 :   rv = NS_NewLocalFile(path, true, getter_AddRefs(localDir));
    1081                 : #elif defined(XP_OS2)
    1082                 : #if 0 /* For OS/2 we want to always use MOZILLA_HOME */
    1083                 :   // we want an environment variable of the form
    1084                 :   // FIREFOX_HOME, etc
    1085                 :   if (!gAppData)
    1086                 :     return NS_ERROR_FAILURE;
    1087                 :   nsDependentCString envVar(nsDependentCString(gAppData->name));
    1088                 :   envVar.Append("_HOME");
    1089                 :   char *pHome = getenv(envVar.get());
    1090                 : #endif
    1091                 :   char *pHome = getenv("MOZILLA_HOME");
    1092                 :   if (pHome && *pHome) {
    1093                 :     rv = NS_NewNativeLocalFile(nsDependentCString(pHome), true,
    1094                 :                                getter_AddRefs(localDir));
    1095                 :   } else {
    1096                 :     PPIB ppib;
    1097                 :     PTIB ptib;
    1098                 :     char appDir[CCHMAXPATH];
    1099                 : 
    1100                 :     DosGetInfoBlocks(&ptib, &ppib);
    1101                 :     DosQueryModuleName(ppib->pib_hmte, CCHMAXPATH, appDir);
    1102                 :     *strrchr(appDir, '\\') = '\0';
    1103                 :     rv = NS_NewNativeLocalFile(nsDependentCString(appDir), true, getter_AddRefs(localDir));
    1104                 :   }
    1105                 : #elif defined(MOZ_WIDGET_GONK)
    1106                 :   rv = NS_NewNativeLocalFile(NS_LITERAL_CSTRING("/data/b2g"), PR_TRUE,
    1107                 :                              getter_AddRefs(localDir));
    1108                 : #elif defined(XP_UNIX)
    1109              22 :   const char* homeDir = getenv("HOME");
    1110              22 :   if (!homeDir || !*homeDir)
    1111               0 :     return NS_ERROR_FAILURE;
    1112                 : 
    1113              22 :   rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
    1114              44 :                              getter_AddRefs(localDir));
    1115                 : #else
    1116                 : #error "Don't know how to get product dir on your platform"
    1117                 : #endif
    1118                 : 
    1119              22 :   NS_IF_ADDREF(*aFile = localDir);
    1120              22 :   return rv;
    1121                 : }
    1122                 : 
    1123                 : nsresult
    1124               0 : nsXREDirProvider::GetSysUserExtensionsDirectory(nsILocalFile** aFile)
    1125                 : {
    1126               0 :   nsCOMPtr<nsILocalFile> localDir;
    1127               0 :   nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), false);
    1128               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1129                 : 
    1130               0 :   rv = AppendSysUserExtensionPath(localDir);
    1131               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1132                 : 
    1133               0 :   rv = EnsureDirectoryExists(localDir);
    1134               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1135                 : 
    1136               0 :   NS_ADDREF(*aFile = localDir);
    1137               0 :   return NS_OK;
    1138                 : }
    1139                 : 
    1140                 : #if defined(XP_UNIX) || defined(XP_MACOSX)
    1141                 : nsresult
    1142               0 : nsXREDirProvider::GetSystemExtensionsDirectory(nsILocalFile** aFile)
    1143                 : {
    1144                 :   nsresult rv;
    1145               0 :   nsCOMPtr<nsILocalFile> localDir;
    1146                 : #if defined(XP_MACOSX)
    1147                 :   FSRef fsRef;
    1148                 :   OSErr err = ::FSFindFolder(kOnSystemDisk, kApplicationSupportFolderType, kCreateFolder, &fsRef);
    1149                 :   NS_ENSURE_FALSE(err, NS_ERROR_FAILURE);
    1150                 : 
    1151                 :   rv = NS_NewNativeLocalFile(EmptyCString(), true, getter_AddRefs(localDir));
    1152                 :   NS_ENSURE_SUCCESS(rv, rv);
    1153                 : 
    1154                 :   nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(localDir);
    1155                 :   NS_ENSURE_TRUE(dirFileMac, NS_ERROR_UNEXPECTED);
    1156                 : 
    1157                 :   rv = dirFileMac->InitWithFSRef(&fsRef);
    1158                 :   NS_ENSURE_SUCCESS(rv, rv);
    1159                 : 
    1160                 :   localDir = do_QueryInterface(dirFileMac, &rv);
    1161                 : 
    1162                 :   static const char* const sXR = "Mozilla";
    1163                 :   rv = localDir->AppendNative(nsDependentCString(sXR));
    1164                 :   NS_ENSURE_SUCCESS(rv, rv);
    1165                 : 
    1166                 :   static const char* const sExtensions = "Extensions";
    1167                 :   rv = localDir->AppendNative(nsDependentCString(sExtensions));
    1168                 :   NS_ENSURE_SUCCESS(rv, rv);
    1169                 : #elif defined(XP_UNIX)
    1170                 :   static const char *const sysSExtDir = 
    1171                 : #ifdef HAVE_USR_LIB64_DIR
    1172                 :     "/usr/lib64/mozilla/extensions";
    1173                 : #else
    1174                 :     "/usr/lib/mozilla/extensions";
    1175                 : #endif
    1176                 : 
    1177               0 :   rv = NS_NewNativeLocalFile(nsDependentCString(sysSExtDir), false,
    1178               0 :                              getter_AddRefs(localDir));
    1179               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1180                 : #endif
    1181                 : 
    1182               0 :   NS_ADDREF(*aFile = localDir);
    1183               0 :   return NS_OK;
    1184                 : }
    1185                 : #endif
    1186                 : 
    1187                 : nsresult
    1188              22 : nsXREDirProvider::GetUserDataDirectory(nsILocalFile** aFile, bool aLocal)
    1189                 : {
    1190              44 :   nsCOMPtr<nsILocalFile> localDir;
    1191              22 :   nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), aLocal);
    1192              22 :   NS_ENSURE_SUCCESS(rv, rv);
    1193                 : 
    1194              22 :   rv = AppendProfilePath(localDir);
    1195              22 :   NS_ENSURE_SUCCESS(rv, rv);
    1196                 : 
    1197                 : #ifdef DEBUG_jungshik
    1198                 :   nsCAutoString cwd;
    1199                 :   localDir->GetNativePath(cwd);
    1200                 :   printf("nsXREDirProvider::GetUserDataDirectory: %s\n", cwd.get());
    1201                 : #endif
    1202              22 :   rv = EnsureDirectoryExists(localDir);
    1203              22 :   NS_ENSURE_SUCCESS(rv, rv);
    1204                 : 
    1205              22 :   NS_ADDREF(*aFile = localDir);
    1206              22 :   return NS_OK;
    1207                 : }
    1208                 : 
    1209                 : nsresult
    1210              22 : nsXREDirProvider::EnsureDirectoryExists(nsIFile* aDirectory)
    1211                 : {
    1212                 :   bool exists;
    1213              22 :   nsresult rv = aDirectory->Exists(&exists);
    1214              22 :   NS_ENSURE_SUCCESS(rv, rv);
    1215                 : #ifdef DEBUG_jungshik
    1216                 :   if (!exists) {
    1217                 :     nsCAutoString cwd;
    1218                 :     aDirectory->GetNativePath(cwd);
    1219                 :     printf("nsXREDirProvider::EnsureDirectoryExists: %s does not\n", cwd.get());
    1220                 :   }
    1221                 : #endif
    1222              22 :   if (!exists)
    1223               0 :     rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0700);
    1224                 : #ifdef DEBUG_jungshik
    1225                 :   if (NS_FAILED(rv))
    1226                 :     NS_WARNING("nsXREDirProvider::EnsureDirectoryExists: create failed");
    1227                 : #endif
    1228                 : 
    1229              22 :   return rv;
    1230                 : }
    1231                 : 
    1232                 : void
    1233               0 : nsXREDirProvider::EnsureProfileFileExists(nsIFile *aFile)
    1234                 : {
    1235                 :   nsresult rv;
    1236                 :   bool exists;
    1237                 : 
    1238               0 :   rv = aFile->Exists(&exists);
    1239               0 :   if (NS_FAILED(rv) || exists) return;
    1240                 : 
    1241               0 :   nsCAutoString leafName;
    1242               0 :   rv = aFile->GetNativeLeafName(leafName);
    1243               0 :   if (NS_FAILED(rv)) return;
    1244                 : 
    1245               0 :   nsCOMPtr<nsIFile> defaultsFile;
    1246               0 :   rv = GetProfileDefaultsDir(getter_AddRefs(defaultsFile));
    1247               0 :   if (NS_FAILED(rv)) return;
    1248                 : 
    1249               0 :   rv = defaultsFile->AppendNative(leafName);
    1250               0 :   if (NS_FAILED(rv)) return;
    1251                 : 
    1252               0 :   defaultsFile->CopyToNative(mProfileDir, EmptyCString());
    1253                 : }
    1254                 : 
    1255                 : nsresult
    1256               0 : nsXREDirProvider::GetProfileDefaultsDir(nsIFile* *aResult)
    1257                 : {
    1258               0 :   NS_ASSERTION(mGREDir, "nsXREDirProvider not initialized.");
    1259               0 :   NS_PRECONDITION(aResult, "Null out-param");
    1260                 : 
    1261                 :   nsresult rv;
    1262               0 :   nsCOMPtr<nsIFile> defaultsDir;
    1263                 : 
    1264               0 :   rv = GetAppDir()->Clone(getter_AddRefs(defaultsDir));
    1265               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1266                 : 
    1267               0 :   rv = defaultsDir->AppendNative(NS_LITERAL_CSTRING("defaults"));
    1268               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1269                 : 
    1270               0 :   rv = defaultsDir->AppendNative(NS_LITERAL_CSTRING("profile"));
    1271               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1272                 : 
    1273               0 :   NS_ADDREF(*aResult = defaultsDir);
    1274               0 :   return NS_OK;
    1275                 : }
    1276                 : 
    1277                 : nsresult
    1278               0 : nsXREDirProvider::AppendSysUserExtensionPath(nsIFile* aFile)
    1279                 : {
    1280               0 :   NS_ASSERTION(aFile, "Null pointer!");
    1281                 : 
    1282                 :   nsresult rv;
    1283                 : 
    1284                 : #if defined (XP_MACOSX) || defined(XP_WIN) || defined(XP_OS2)
    1285                 : 
    1286                 :   static const char* const sXR = "Mozilla";
    1287                 :   rv = aFile->AppendNative(nsDependentCString(sXR));
    1288                 :   NS_ENSURE_SUCCESS(rv, rv);
    1289                 : 
    1290                 :   static const char* const sExtensions = "Extensions";
    1291                 :   rv = aFile->AppendNative(nsDependentCString(sExtensions));
    1292                 :   NS_ENSURE_SUCCESS(rv, rv);
    1293                 : 
    1294                 : #elif defined(XP_UNIX)
    1295                 : 
    1296                 :   static const char* const sXR = ".mozilla";
    1297               0 :   rv = aFile->AppendNative(nsDependentCString(sXR));
    1298               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1299                 : 
    1300                 :   static const char* const sExtensions = "extensions";
    1301               0 :   rv = aFile->AppendNative(nsDependentCString(sExtensions));
    1302               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1303                 : 
    1304                 : #else
    1305                 : #error "Don't know how to get XRE user extension path on your platform"
    1306                 : #endif
    1307               0 :   return NS_OK;
    1308                 : }
    1309                 : 
    1310                 : 
    1311                 : nsresult
    1312              22 : nsXREDirProvider::AppendProfilePath(nsIFile* aFile)
    1313                 : {
    1314              22 :   NS_ASSERTION(aFile, "Null pointer!");
    1315                 : 
    1316                 :   nsresult rv;
    1317                 : 
    1318              22 :   if (!gAppData)
    1319               0 :     return NS_ERROR_FAILURE;
    1320                 : 
    1321                 : #if defined (XP_MACOSX)
    1322                 :   if (gAppData->profile) {
    1323                 :     rv = AppendProfileString(aFile, gAppData->profile);
    1324                 :   }
    1325                 :   else {
    1326                 :     // Note that MacOS ignores the vendor when creating the profile hierarchy -
    1327                 :     // all application preferences directories live alongside one another in
    1328                 :     // ~/Library/Application Support/
    1329                 :     rv = aFile->AppendNative(nsDependentCString(gAppData->name));
    1330                 :   }
    1331                 :   NS_ENSURE_SUCCESS(rv, rv);
    1332                 : 
    1333                 : #elif defined(XP_WIN) || defined(XP_OS2)
    1334                 :   if (gAppData->profile) {
    1335                 :     rv = AppendProfileString(aFile, gAppData->profile);
    1336                 :   }
    1337                 :   else {
    1338                 :     if (gAppData->vendor) {
    1339                 :       rv = aFile->AppendNative(nsDependentCString(gAppData->vendor));
    1340                 :       NS_ENSURE_SUCCESS(rv, rv);
    1341                 :     }
    1342                 :     rv = aFile->AppendNative(nsDependentCString(gAppData->name));
    1343                 :   }
    1344                 :   NS_ENSURE_SUCCESS(rv, rv);
    1345                 : 
    1346                 : #elif defined(ANDROID)
    1347                 :   // The directory used for storing profiles
    1348                 :   // The parent of this directory is set in GetUserDataDirectoryHome
    1349                 :   // XXX: handle gAppData->profile properly
    1350                 :   rv = aFile->AppendNative(nsDependentCString("mozilla"));
    1351                 :   NS_ENSURE_SUCCESS(rv, rv);
    1352                 : #elif defined(XP_UNIX)
    1353                 :   // Make it hidden (i.e. using the ".")
    1354              44 :   nsCAutoString folder(".");
    1355                 : 
    1356              22 :   if (gAppData->profile) {
    1357                 :     // Skip any leading path characters
    1358               0 :     const char* profileStart = gAppData->profile;
    1359               0 :     while (*profileStart == '/' || *profileStart == '\\')
    1360               0 :       profileStart++;
    1361                 : 
    1362                 :     // On the off chance that someone wanted their folder to be hidden don't
    1363                 :     // let it become ".."
    1364               0 :     if (*profileStart == '.')
    1365               0 :       profileStart++;
    1366                 : 
    1367               0 :     folder.Append(profileStart);
    1368               0 :     ToLowerCase(folder);
    1369                 : 
    1370               0 :     rv = AppendProfileString(aFile, folder.BeginReading());
    1371                 :   }
    1372                 :   else {
    1373              22 :     if (gAppData->vendor) {
    1374              22 :       folder.Append(gAppData->vendor);
    1375              22 :       ToLowerCase(folder);
    1376                 : 
    1377              22 :       rv = aFile->AppendNative(folder);
    1378              22 :       NS_ENSURE_SUCCESS(rv, rv);
    1379                 : 
    1380              22 :       folder.Truncate();
    1381                 :     }
    1382                 : 
    1383              22 :     folder.Append(gAppData->name);
    1384              22 :     ToLowerCase(folder);
    1385                 : 
    1386              22 :     rv = aFile->AppendNative(folder);
    1387                 :   }
    1388              22 :   NS_ENSURE_SUCCESS(rv, rv);
    1389                 : 
    1390                 : #else
    1391                 : #error "Don't know how to get profile path on your platform"
    1392                 : #endif
    1393              22 :   return NS_OK;
    1394                 : }
    1395                 : 
    1396                 : nsresult
    1397               0 : nsXREDirProvider::AppendProfileString(nsIFile* aFile, const char* aPath)
    1398                 : {
    1399               0 :   NS_ASSERTION(aFile, "Null file!");
    1400               0 :   NS_ASSERTION(aPath, "Null path!");
    1401                 : 
    1402               0 :   nsCAutoString pathDup(aPath);
    1403                 : 
    1404               0 :   char* path = pathDup.BeginWriting();
    1405                 : 
    1406                 :   nsresult rv;
    1407                 :   char* subdir;
    1408               0 :   while ((subdir = NS_strtok("/\\", &path))) {
    1409               0 :     rv = aFile->AppendNative(nsDependentCString(subdir));
    1410               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1411                 :   }
    1412                 : 
    1413               0 :   return NS_OK;
    1414                 : }

Generated by: LCOV version 1.7