LCOV - code coverage report
Current view: top level - toolkit/xre - nsXREDirProvider.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 309 514 60.1 %
Date: 2017-07-14 16:53:18 Functions: 19 30 63.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsAppRunner.h"
       7             : #include "nsToolkitCompsCID.h"
       8             : #include "nsXREDirProvider.h"
       9             : #include "mozilla/AddonManagerStartup.h"
      10             : 
      11             : #include "jsapi.h"
      12             : #include "xpcpublic.h"
      13             : 
      14             : #include "nsIAddonInterposition.h"
      15             : #include "nsIAppStartup.h"
      16             : #include "nsIDirectoryEnumerator.h"
      17             : #include "nsIFile.h"
      18             : #include "nsIObserver.h"
      19             : #include "nsIObserverService.h"
      20             : #include "nsISimpleEnumerator.h"
      21             : #include "nsIToolkitChromeRegistry.h"
      22             : #include "nsIToolkitProfileService.h"
      23             : #include "nsIXULRuntime.h"
      24             : 
      25             : #include "nsAppDirectoryServiceDefs.h"
      26             : #include "nsDirectoryServiceDefs.h"
      27             : #include "nsDirectoryServiceUtils.h"
      28             : #include "nsXULAppAPI.h"
      29             : #include "nsCategoryManagerUtils.h"
      30             : 
      31             : #include "nsDependentString.h"
      32             : #include "nsCOMArray.h"
      33             : #include "nsArrayEnumerator.h"
      34             : #include "nsEnumeratorUtils.h"
      35             : #include "nsReadableUtils.h"
      36             : 
      37             : #include "SpecialSystemDirectory.h"
      38             : 
      39             : #include "mozilla/dom/ScriptSettings.h"
      40             : 
      41             : #include "mozilla/Services.h"
      42             : #include "mozilla/Omnijar.h"
      43             : #include "mozilla/Preferences.h"
      44             : #include "mozilla/Telemetry.h"
      45             : 
      46             : #include <stdlib.h>
      47             : 
      48             : #ifdef XP_WIN
      49             : #include "city.h"
      50             : #include <windows.h>
      51             : #include <shlobj.h>
      52             : #endif
      53             : #ifdef XP_MACOSX
      54             : #include "nsILocalFileMac.h"
      55             : // for chflags()
      56             : #include <sys/stat.h>
      57             : #include <unistd.h>
      58             : #endif
      59             : #ifdef XP_UNIX
      60             : #include <ctype.h>
      61             : #endif
      62             : #ifdef XP_IOS
      63             : #include "UIKitDirProvider.h"
      64             : #endif
      65             : 
      66             : #if defined(MOZ_CONTENT_SANDBOX)
      67             : #include "mozilla/SandboxSettings.h"
      68             : #if (defined(XP_WIN) || defined(XP_MACOSX))
      69             : #include "nsIUUIDGenerator.h"
      70             : #include "mozilla/Unused.h"
      71             : #if defined(XP_WIN)
      72             : #include "WinUtils.h"
      73             : #endif
      74             : #endif
      75             : #endif
      76             : 
      77             : #if defined(XP_MACOSX)
      78             : #define APP_REGISTRY_NAME "Application Registry"
      79             : #elif defined(XP_WIN)
      80             : #define APP_REGISTRY_NAME "registry.dat"
      81             : #else
      82             : #define APP_REGISTRY_NAME "appreg"
      83             : #endif
      84             : 
      85             : #define PREF_OVERRIDE_DIRNAME "preferences"
      86             : 
      87             : #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
      88             : static already_AddRefed<nsIFile> GetContentProcessSandboxTempDir();
      89             : static nsresult DeleteDirIfExists(nsIFile *dir);
      90             : static bool IsContentSandboxDisabled();
      91             : static const char* GetContentProcessTempBaseDirKey();
      92             : static already_AddRefed<nsIFile> CreateContentProcessSandboxTempDir();
      93             : #endif
      94             : 
      95             : nsXREDirProvider* gDirServiceProvider = nullptr;
      96             : 
      97           3 : nsXREDirProvider::nsXREDirProvider() :
      98           3 :   mProfileNotified(false)
      99             : {
     100           3 :   gDirServiceProvider = this;
     101           3 : }
     102             : 
     103           0 : nsXREDirProvider::~nsXREDirProvider()
     104             : {
     105           0 :   gDirServiceProvider = nullptr;
     106           0 : }
     107             : 
     108             : nsXREDirProvider*
     109           0 : nsXREDirProvider::GetSingleton()
     110             : {
     111           0 :   return gDirServiceProvider;
     112             : }
     113             : 
     114             : nsresult
     115           3 : nsXREDirProvider::Initialize(nsIFile *aXULAppDir,
     116             :                              nsIFile *aGREDir,
     117             :                              nsIDirectoryServiceProvider* aAppProvider)
     118             : {
     119           3 :   NS_ENSURE_ARG(aXULAppDir);
     120           3 :   NS_ENSURE_ARG(aGREDir);
     121             : 
     122           3 :   mAppProvider = aAppProvider;
     123           3 :   mXULAppDir = aXULAppDir;
     124           3 :   mGREDir = aGREDir;
     125             : #if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
     126             :   // The GRE directory can be used in sandbox rules, so we need to make sure
     127             :   // it doesn't contain any junction points or symlinks or the sandbox will
     128             :   // reject those rules.
     129             :   if (!mozilla::widget::WinUtils::ResolveJunctionPointsAndSymLinks(mGREDir)) {
     130             :     NS_WARNING("Failed to resolve GRE Dir.");
     131             :   }
     132             :   // If the mXULAppDir is different it lives below the mGREDir. To avoid
     133             :   // confusion resolve that as well even though we don't need it for sandbox
     134             :   // rules. Some tests rely on this for example.
     135             :   if (!mozilla::widget::WinUtils::ResolveJunctionPointsAndSymLinks(mXULAppDir)) {
     136             :     NS_WARNING("Failed to resolve XUL App Dir.");
     137             :   }
     138             : #endif
     139           3 :   mGREDir->Clone(getter_AddRefs(mGREBinDir));
     140             : #ifdef XP_MACOSX
     141             :   mGREBinDir->SetNativeLeafName(NS_LITERAL_CSTRING("MacOS"));
     142             : #endif
     143             : 
     144           3 :   if (!mProfileDir) {
     145           6 :     nsCOMPtr<nsIDirectoryServiceProvider> app(do_QueryInterface(mAppProvider));
     146           3 :     if (app) {
     147           0 :       bool per = false;
     148           0 :       app->GetFile(NS_APP_USER_PROFILE_50_DIR, &per, getter_AddRefs(mProfileDir));
     149           0 :       NS_ASSERTION(per, "NS_APP_USER_PROFILE_50_DIR must be persistent!");
     150           0 :       NS_ASSERTION(mProfileDir, "NS_APP_USER_PROFILE_50_DIR not defined! This shouldn't happen!");
     151             :     }
     152             :   }
     153             : 
     154             : #ifdef MOZ_B2G
     155             :   LoadAppBundleDirs();
     156             : #endif
     157             : 
     158           3 :   return NS_OK;
     159             : }
     160             : 
     161             : nsresult
     162           1 : nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir)
     163             : {
     164           1 :   NS_ASSERTION(aDir && aLocalDir, "We don't support no-profile apps yet!");
     165             : 
     166             :   nsresult rv;
     167             : 
     168           1 :   rv = EnsureDirectoryExists(aDir);
     169           1 :   if (NS_FAILED(rv))
     170           0 :     return rv;
     171             : 
     172           1 :   rv = EnsureDirectoryExists(aLocalDir);
     173           1 :   if (NS_FAILED(rv))
     174           0 :     return rv;
     175             : 
     176             : #ifdef XP_MACOSX
     177             :   bool same;
     178             :   if (NS_SUCCEEDED(aDir->Equals(aLocalDir, &same)) && !same) {
     179             :     // Ensure that the cache directory is not indexed by Spotlight
     180             :     // (bug 718910).  At least on OS X, the cache directory (under
     181             :     // ~/Library/Caches/) is always the "local" user profile
     182             :     // directory.  This is confusing, since *both* user profile
     183             :     // directories are "local" (they both exist under the user's
     184             :     // home directory).  But this usage dates back at least as far
     185             :     // as the patch for bug 291033, where "local" seems to mean
     186             :     // "suitable for temporary storage".  Don't hide the cache
     187             :     // directory if by some chance it and the "non-local" profile
     188             :     // directory are the same -- there are bad side effects from
     189             :     // hiding a profile directory under /Library/Application Support/
     190             :     // (see bug 801883).
     191             :     nsAutoCString cacheDir;
     192             :     if (NS_SUCCEEDED(aLocalDir->GetNativePath(cacheDir))) {
     193             :       if (chflags(cacheDir.get(), UF_HIDDEN)) {
     194             :         NS_WARNING("Failed to set Cache directory to HIDDEN.");
     195             :       }
     196             :     }
     197             :   }
     198             : #endif
     199             : 
     200           1 :   mProfileDir = aDir;
     201           1 :   mProfileLocalDir = aLocalDir;
     202             : #if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
     203             :   // The profile directory can be used in sandbox rules, so we need to make sure
     204             :   // it doesn't contain any junction points or symlinks or the sandbox will
     205             :   // reject those rules.
     206             :   if (!mozilla::widget::WinUtils::ResolveJunctionPointsAndSymLinks(mProfileDir)) {
     207             :     NS_WARNING("Failed to resolve Profile Dir.");
     208             :   }
     209             : #endif
     210           1 :   return NS_OK;
     211             : }
     212             : 
     213          23 : NS_IMPL_QUERY_INTERFACE(nsXREDirProvider,
     214             :                         nsIDirectoryServiceProvider,
     215             :                         nsIDirectoryServiceProvider2,
     216             :                         nsIProfileStartup)
     217             : 
     218             : NS_IMETHODIMP_(MozExternalRefCountType)
     219          26 : nsXREDirProvider::AddRef()
     220             : {
     221          26 :   return 1;
     222             : }
     223             : 
     224             : NS_IMETHODIMP_(MozExternalRefCountType)
     225          23 : nsXREDirProvider::Release()
     226             : {
     227          23 :   return 0;
     228             : }
     229             : 
     230             : nsresult
     231           0 : nsXREDirProvider::GetUserProfilesRootDir(nsIFile** aResult,
     232             :                                          const nsACString* aProfileName,
     233             :                                          const nsACString* aAppName,
     234             :                                          const nsACString* aVendorName)
     235             : {
     236           0 :   nsCOMPtr<nsIFile> file;
     237           0 :   nsresult rv = GetUserDataDirectory(getter_AddRefs(file),
     238             :                                      false,
     239           0 :                                      aProfileName, aAppName, aVendorName);
     240             : 
     241           0 :   if (NS_SUCCEEDED(rv)) {
     242             : #if !defined(XP_UNIX) || defined(XP_MACOSX)
     243             :     rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
     244             : #endif
     245             :     // We must create the profile directory here if it does not exist.
     246           0 :     nsresult tmp = EnsureDirectoryExists(file);
     247           0 :     if (NS_FAILED(tmp)) {
     248           0 :       rv = tmp;
     249             :     }
     250             :   }
     251           0 :   file.swap(*aResult);
     252           0 :   return rv;
     253             : }
     254             : 
     255             : nsresult
     256           0 : nsXREDirProvider::GetUserProfilesLocalDir(nsIFile** aResult,
     257             :                                           const nsACString* aProfileName,
     258             :                                           const nsACString* aAppName,
     259             :                                           const nsACString* aVendorName)
     260             : {
     261           0 :   nsCOMPtr<nsIFile> file;
     262           0 :   nsresult rv = GetUserDataDirectory(getter_AddRefs(file),
     263             :                                      true,
     264           0 :                                      aProfileName, aAppName, aVendorName);
     265             : 
     266           0 :   if (NS_SUCCEEDED(rv)) {
     267             : #if !defined(XP_UNIX) || defined(XP_MACOSX)
     268             :     rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
     269             : #endif
     270             :     // We must create the profile directory here if it does not exist.
     271           0 :     nsresult tmp = EnsureDirectoryExists(file);
     272           0 :     if (NS_FAILED(tmp)) {
     273           0 :       rv = tmp;
     274             :     }
     275             :   }
     276           0 :   file.swap(*aResult);
     277           0 :   return NS_OK;
     278             : }
     279             : 
     280             : #if defined(XP_UNIX) || defined(XP_MACOSX)
     281             : /**
     282             :  * Get the directory that is the parent of the system-wide directories
     283             :  * for extensions and native-messaing manifests.
     284             :  *
     285             :  * On OSX this is /Library/Application Support/Mozilla
     286             :  * On Linux this is /usr/{lib,lib64}/mozilla
     287             :  *   (for 32- and 64-bit systems respsectively)
     288             :  */
     289             : static nsresult
     290           0 : GetSystemParentDirectory(nsIFile** aFile)
     291             : {
     292             :   nsresult rv;
     293           0 :   nsCOMPtr<nsIFile> localDir;
     294             : #if defined(XP_MACOSX)
     295             :   rv = GetOSXFolderType(kOnSystemDisk, kApplicationSupportFolderType, getter_AddRefs(localDir));
     296             :   if (NS_SUCCEEDED(rv)) {
     297             :     rv = localDir->AppendNative(NS_LITERAL_CSTRING("Mozilla"));
     298             :   }
     299             : #else
     300           0 :   NS_NAMED_LITERAL_CSTRING(dirname,
     301             : #ifdef HAVE_USR_LIB64_DIR
     302             :                            "/usr/lib64/mozilla"
     303             : #elif defined(__OpenBSD__) || defined(__FreeBSD__)
     304             :                            "/usr/local/lib/mozilla"
     305             : #else
     306             :                            "/usr/lib/mozilla"
     307             : #endif
     308             :                            );
     309           0 :   rv = NS_NewNativeLocalFile(dirname, false, getter_AddRefs(localDir));
     310             : #endif
     311             : 
     312           0 :   if (NS_SUCCEEDED(rv)) {
     313           0 :     localDir.forget(aFile);
     314             :   }
     315           0 :   return rv;
     316             : }
     317             : #endif
     318             : 
     319             : NS_IMETHODIMP
     320          46 : nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
     321             :                           nsIFile** aFile)
     322             : {
     323             :   nsresult rv;
     324             : 
     325          46 :   bool gettingProfile = false;
     326             : 
     327          46 :   if (!strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR)) {
     328             :     // If XRE_NotifyProfile hasn't been called, don't fall through to
     329             :     // mAppProvider on the profile keys.
     330           1 :     if (!mProfileNotified)
     331           0 :       return NS_ERROR_FAILURE;
     332             : 
     333           1 :     if (mProfileLocalDir)
     334           1 :       return mProfileLocalDir->Clone(aFile);
     335             : 
     336           0 :     if (mAppProvider)
     337           0 :       return mAppProvider->GetFile(aProperty, aPersistent, aFile);
     338             : 
     339             :     // This falls through to the case below
     340           0 :     gettingProfile = true;
     341             :   }
     342          45 :   if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) || gettingProfile) {
     343           4 :     if (!mProfileNotified)
     344           3 :       return NS_ERROR_FAILURE;
     345             : 
     346           1 :     if (mProfileDir)
     347           1 :       return mProfileDir->Clone(aFile);
     348             : 
     349           0 :     if (mAppProvider)
     350           0 :       return mAppProvider->GetFile(aProperty, aPersistent, aFile);
     351             : 
     352             :     // If we don't succeed here, bail early so that we aren't reentrant
     353             :     // through the "GetProfileDir" call below.
     354           0 :     return NS_ERROR_FAILURE;
     355             :   }
     356             : 
     357          41 :   if (mAppProvider) {
     358           0 :     rv = mAppProvider->GetFile(aProperty, aPersistent, aFile);
     359           0 :     if (NS_SUCCEEDED(rv) && *aFile)
     360           0 :       return rv;
     361             :   }
     362             : 
     363          41 :   *aPersistent = true;
     364             : 
     365          41 :   if (!strcmp(aProperty, NS_GRE_DIR)) {
     366           4 :     return mGREDir->Clone(aFile);
     367             :   }
     368          37 :   else if (!strcmp(aProperty, NS_GRE_BIN_DIR)) {
     369           3 :     return mGREBinDir->Clone(aFile);
     370             :   }
     371          68 :   else if (!strcmp(aProperty, NS_OS_CURRENT_PROCESS_DIR) ||
     372          34 :            !strcmp(aProperty, NS_APP_INSTALL_CLEANUP_DIR)) {
     373           0 :     return GetAppDir()->Clone(aFile);
     374             :   }
     375             : 
     376          34 :   rv = NS_ERROR_FAILURE;
     377          68 :   nsCOMPtr<nsIFile> file;
     378             : 
     379          34 :   if (!strcmp(aProperty, NS_APP_PREF_DEFAULTS_50_DIR))
     380             :   {
     381             :     // return the GRE default prefs directory here, and the app default prefs
     382             :     // directory (if applicable) in NS_APP_PREFS_DEFAULTS_DIR_LIST.
     383           3 :     rv = mGREDir->Clone(getter_AddRefs(file));
     384           3 :     if (NS_SUCCEEDED(rv)) {
     385           3 :       rv = file->AppendNative(NS_LITERAL_CSTRING("defaults"));
     386           3 :       if (NS_SUCCEEDED(rv))
     387           3 :         rv = file->AppendNative(NS_LITERAL_CSTRING("pref"));
     388             :     }
     389             :   }
     390          62 :   else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_DIR) ||
     391          31 :            !strcmp(aProperty, XRE_USER_APP_DATA_DIR)) {
     392           1 :     rv = GetUserAppDataDirectory(getter_AddRefs(file));
     393             :   }
     394             : #if defined(XP_UNIX) || defined(XP_MACOSX)
     395          30 :   else if (!strcmp(aProperty, XRE_SYS_NATIVE_MESSAGING_MANIFESTS)) {
     396           0 :     nsCOMPtr<nsIFile> localDir;
     397             : 
     398           0 :     rv = ::GetSystemParentDirectory(getter_AddRefs(localDir));
     399           0 :     if (NS_SUCCEEDED(rv)) {
     400           0 :       NS_NAMED_LITERAL_CSTRING(dirname,
     401             : #if defined(XP_MACOSX)
     402             :                                "NativeMessagingHosts"
     403             : #else
     404             :                                "native-messaging-hosts"
     405             : #endif
     406             :                                );
     407           0 :       rv = localDir->AppendNative(dirname);
     408           0 :       if (NS_SUCCEEDED(rv)) {
     409           0 :         localDir.swap(file);
     410             :       }
     411             :     }
     412             :   }
     413          30 :   else if (!strcmp(aProperty, XRE_USER_NATIVE_MESSAGING_MANIFESTS)) {
     414           0 :     nsCOMPtr<nsIFile> localDir;
     415           0 :     rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), false);
     416           0 :     if (NS_SUCCEEDED(rv)) {
     417             : #if defined(XP_MACOSX)
     418             :       rv = localDir->AppendNative(NS_LITERAL_CSTRING("Mozilla"));
     419             :       if (NS_SUCCEEDED(rv)) {
     420             :         rv = localDir->AppendNative(NS_LITERAL_CSTRING("NativeMessagingHosts"));
     421             :       }
     422             : #else
     423           0 :       rv = localDir->AppendNative(NS_LITERAL_CSTRING(".mozilla"));
     424           0 :       if (NS_SUCCEEDED(rv)) {
     425           0 :         rv = localDir->AppendNative(NS_LITERAL_CSTRING("native-messaging-hosts"));
     426             :       }
     427             : #endif
     428             :     }
     429           0 :     if (NS_SUCCEEDED(rv)) {
     430           0 :       localDir.swap(file);
     431             :     }
     432             :   }
     433             : #endif
     434          30 :   else if (!strcmp(aProperty, XRE_UPDATE_ROOT_DIR)) {
     435           2 :     rv = GetUpdateRootDir(getter_AddRefs(file));
     436             :   }
     437          28 :   else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_FILE)) {
     438           0 :     rv = GetUserAppDataDirectory(getter_AddRefs(file));
     439           0 :     if (NS_SUCCEEDED(rv))
     440           0 :       rv = file->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME));
     441             :   }
     442          28 :   else if (!strcmp(aProperty, NS_APP_USER_PROFILES_ROOT_DIR)) {
     443           0 :     rv = GetUserProfilesRootDir(getter_AddRefs(file), nullptr, nullptr, nullptr);
     444             :   }
     445          28 :   else if (!strcmp(aProperty, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR)) {
     446           0 :     rv = GetUserProfilesLocalDir(getter_AddRefs(file), nullptr, nullptr, nullptr);
     447             :   }
     448          28 :   else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) {
     449           6 :     nsCOMPtr<nsIFile> lf;
     450           3 :     rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
     451           3 :     if (NS_SUCCEEDED(rv))
     452           6 :       file = lf;
     453             :   }
     454             : 
     455          25 :   else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) {
     456           1 :     return mProfileDir->Clone(aFile);
     457             :   }
     458          24 :   else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
     459           1 :     if (mProfileLocalDir)
     460           1 :       return mProfileLocalDir->Clone(aFile);
     461             : 
     462           0 :     if (mProfileDir)
     463           0 :       return mProfileDir->Clone(aFile);
     464             : 
     465           0 :     if (mAppProvider)
     466           0 :       return mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP, aPersistent,
     467           0 :                                    aFile);
     468             :   }
     469             : #if defined(XP_UNIX) || defined(XP_MACOSX)
     470          23 :   else if (!strcmp(aProperty, XRE_SYS_LOCAL_EXTENSION_PARENT_DIR)) {
     471             : #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
     472           0 :     return GetSystemExtensionsDirectory(aFile);
     473             : #else
     474             :     return NS_ERROR_FAILURE;
     475             : #endif
     476             :   }
     477             : #endif
     478             : #if defined(XP_UNIX) && !defined(XP_MACOSX)
     479          23 :   else if (!strcmp(aProperty, XRE_SYS_SHARE_EXTENSION_PARENT_DIR)) {
     480             : #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
     481             : #if defined(__OpenBSD__) || defined(__FreeBSD__)
     482             :     static const char *const sysLExtDir = "/usr/local/share/mozilla/extensions";
     483             : #else
     484             :     static const char *const sysLExtDir = "/usr/share/mozilla/extensions";
     485             : #endif
     486           0 :     return NS_NewNativeLocalFile(nsDependentCString(sysLExtDir),
     487           0 :                                  false, aFile);
     488             : #else
     489             :     return NS_ERROR_FAILURE;
     490             : #endif
     491             :   }
     492             : #endif
     493          23 :   else if (!strcmp(aProperty, XRE_USER_SYS_EXTENSION_DIR)) {
     494             : #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
     495           0 :     return GetSysUserExtensionsDirectory(aFile);
     496             : #else
     497             :     return NS_ERROR_FAILURE;
     498             : #endif
     499             :   }
     500          23 :   else if (!strcmp(aProperty, XRE_APP_DISTRIBUTION_DIR)) {
     501           1 :     bool persistent = false;
     502           1 :     rv = GetFile(NS_GRE_DIR, &persistent, getter_AddRefs(file));
     503           1 :     if (NS_SUCCEEDED(rv))
     504           1 :       rv = file->AppendNative(NS_LITERAL_CSTRING("distribution"));
     505             :   }
     506          22 :   else if (!strcmp(aProperty, XRE_APP_FEATURES_DIR)) {
     507           1 :     rv = GetAppDir()->Clone(getter_AddRefs(file));
     508           1 :     if (NS_SUCCEEDED(rv))
     509           1 :       rv = file->AppendNative(NS_LITERAL_CSTRING("features"));
     510             :   }
     511          21 :   else if (!strcmp(aProperty, XRE_ADDON_APP_DIR)) {
     512           2 :     nsCOMPtr<nsIDirectoryServiceProvider> dirsvc(do_GetService("@mozilla.org/file/directory_service;1", &rv));
     513           1 :     if (NS_FAILED(rv))
     514           0 :       return rv;
     515             :     bool unused;
     516           1 :     rv = dirsvc->GetFile("XCurProcD", &unused, getter_AddRefs(file));
     517             :   }
     518             : #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
     519             :   else if (!strcmp(aProperty, NS_APP_CONTENT_PROCESS_TEMP_DIR)) {
     520             :     if (!mContentTempDir && NS_FAILED((rv = LoadContentProcessTempDir()))) {
     521             :       return rv;
     522             :     }
     523             :     rv = mContentTempDir->Clone(getter_AddRefs(file));
     524             :   }
     525             : #endif // defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
     526          20 :   else if (NS_SUCCEEDED(GetProfileStartupDir(getter_AddRefs(file)))) {
     527             :     // We need to allow component, xpt, and chrome registration to
     528             :     // occur prior to the profile-after-change notification.
     529          15 :     if (!strcmp(aProperty, NS_APP_USER_CHROME_DIR)) {
     530           1 :       rv = file->AppendNative(NS_LITERAL_CSTRING("chrome"));
     531             :     }
     532             :   }
     533             : 
     534          32 :   if (NS_SUCCEEDED(rv) && file) {
     535          13 :     file.forget(aFile);
     536          13 :     return NS_OK;
     537             :   }
     538             : 
     539          19 :   bool ensureFilePermissions = false;
     540             : 
     541          19 :   if (NS_SUCCEEDED(GetProfileDir(getter_AddRefs(file)))) {
     542          12 :     if (!strcmp(aProperty, NS_APP_PREFS_50_DIR)) {
     543           1 :       rv = NS_OK;
     544             :     }
     545          11 :     else if (!strcmp(aProperty, NS_APP_PREFS_50_FILE)) {
     546           1 :       rv = file->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
     547             :     }
     548          10 :     else if (!strcmp(aProperty, NS_LOCALSTORE_UNSAFE_FILE)) {
     549           0 :       rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
     550             :     }
     551          10 :     else if (!strcmp(aProperty, NS_APP_LOCALSTORE_50_FILE)) {
     552           0 :       if (gSafeMode) {
     553           0 :         rv = file->AppendNative(NS_LITERAL_CSTRING("localstore-safe.rdf"));
     554           0 :         file->Remove(false);
     555             :       }
     556             :       else {
     557           0 :         rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
     558           0 :         ensureFilePermissions = true;
     559             :       }
     560             :     }
     561          10 :     else if (!strcmp(aProperty, NS_APP_PREFS_OVERRIDE_DIR)) {
     562           0 :       rv = mProfileDir->Clone(getter_AddRefs(file));
     563           0 :       nsresult tmp = file->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));
     564           0 :       if (NS_FAILED(tmp)) {
     565           0 :         rv = tmp;
     566             :       }
     567           0 :       tmp = EnsureDirectoryExists(file);
     568           0 :       if (NS_FAILED(tmp)) {
     569           0 :         rv = tmp;
     570             :       }
     571             :     }
     572             :   }
     573          19 :   if (NS_FAILED(rv) || !file)
     574          17 :     return NS_ERROR_FAILURE;
     575             : 
     576           2 :   if (ensureFilePermissions) {
     577             :     bool fileToEnsureExists;
     578             :     bool isWritable;
     579           0 :     if (NS_SUCCEEDED(file->Exists(&fileToEnsureExists)) && fileToEnsureExists
     580           0 :         && NS_SUCCEEDED(file->IsWritable(&isWritable)) && !isWritable) {
     581             :       uint32_t permissions;
     582           0 :       if (NS_SUCCEEDED(file->GetPermissions(&permissions))) {
     583           0 :         rv = file->SetPermissions(permissions | 0600);
     584           0 :         NS_ASSERTION(NS_SUCCEEDED(rv), "failed to ensure file permissions");
     585             :       }
     586             :     }
     587             :   }
     588             : 
     589           2 :   file.forget(aFile);
     590           2 :   return NS_OK;
     591             : }
     592             : 
     593             : static void
     594          40 : LoadDirIntoArray(nsIFile* dir,
     595             :                  const char *const *aAppendList,
     596             :                  nsCOMArray<nsIFile>& aDirectories)
     597             : {
     598          40 :   if (!dir)
     599           0 :     return;
     600             : 
     601          80 :   nsCOMPtr<nsIFile> subdir;
     602          40 :   dir->Clone(getter_AddRefs(subdir));
     603          40 :   if (!subdir)
     604           0 :     return;
     605             : 
     606          83 :   for (const char *const *a = aAppendList; *a; ++a) {
     607          43 :     subdir->AppendNative(nsDependentCString(*a));
     608             :   }
     609             : 
     610             :   bool exists;
     611          40 :   if (NS_SUCCEEDED(subdir->Exists(&exists)) && exists) {
     612          35 :     aDirectories.AppendObject(subdir);
     613             :   }
     614             : }
     615             : 
     616             : static void
     617          32 : LoadDirsIntoArray(const nsCOMArray<nsIFile>& aSourceDirs,
     618             :                   const char *const* aAppendList,
     619             :                   nsCOMArray<nsIFile>& aDirectories)
     620             : {
     621          64 :   nsCOMPtr<nsIFile> appended;
     622             :   bool exists;
     623             : 
     624          59 :   for (int32_t i = 0; i < aSourceDirs.Count(); ++i) {
     625          27 :     aSourceDirs[i]->Clone(getter_AddRefs(appended));
     626          27 :     if (!appended)
     627           0 :       continue;
     628             : 
     629          54 :     nsAutoCString leaf;
     630          27 :     appended->GetNativeLeafName(leaf);
     631          27 :     if (!Substring(leaf, leaf.Length() - 4).EqualsLiteral(".xpi")) {
     632          27 :       LoadDirIntoArray(appended,
     633             :                        aAppendList,
     634          27 :                        aDirectories);
     635             :     }
     636           0 :     else if (NS_SUCCEEDED(appended->Exists(&exists)) && exists)
     637           0 :       aDirectories.AppendObject(appended);
     638             :   }
     639          32 : }
     640             : 
     641             : NS_IMETHODIMP
     642          20 : nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult)
     643             : {
     644             :   nsresult rv;
     645             : 
     646          40 :   nsCOMPtr<nsISimpleEnumerator> appEnum;
     647             :   nsCOMPtr<nsIDirectoryServiceProvider2>
     648          40 :     appP2(do_QueryInterface(mAppProvider));
     649          20 :   if (appP2) {
     650           0 :     rv = appP2->GetFiles(aProperty, getter_AddRefs(appEnum));
     651           0 :     if (NS_FAILED(rv)) {
     652           0 :       appEnum = nullptr;
     653             :     }
     654           0 :     else if (rv != NS_SUCCESS_AGGREGATE_RESULT) {
     655           0 :       appEnum.forget(aResult);
     656           0 :       return NS_OK;
     657             :     }
     658             :   }
     659             : 
     660          40 :   nsCOMPtr<nsISimpleEnumerator> xreEnum;
     661          20 :   rv = GetFilesInternal(aProperty, getter_AddRefs(xreEnum));
     662          20 :   if (NS_FAILED(rv)) {
     663           1 :     if (appEnum) {
     664           0 :       appEnum.forget(aResult);
     665           0 :       return NS_SUCCESS_AGGREGATE_RESULT;
     666             :     }
     667             : 
     668           1 :     return rv;
     669             :   }
     670             : 
     671          19 :   rv = NS_NewUnionEnumerator(aResult, appEnum, xreEnum);
     672          19 :   if (NS_FAILED(rv))
     673           0 :     return rv;
     674             : 
     675          19 :   return NS_SUCCESS_AGGREGATE_RESULT;
     676             : }
     677             : 
     678             : #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
     679             : 
     680             : static const char*
     681             : GetContentProcessTempBaseDirKey()
     682             : {
     683             : #if defined(XP_WIN)
     684             :   return NS_WIN_LOW_INTEGRITY_TEMP_BASE;
     685             : #else
     686             :   return NS_OS_TEMP_DIR;
     687             : #endif
     688             : }
     689             : 
     690             : //
     691             : // Sets mContentTempDir so that it refers to the appropriate temp dir.
     692             : // If the sandbox is enabled, NS_APP_CONTENT_PROCESS_TEMP_DIR, otherwise
     693             : // NS_OS_TEMP_DIR is used.
     694             : //
     695             : nsresult
     696             : nsXREDirProvider::LoadContentProcessTempDir()
     697             : {
     698             :   // The parent is responsible for creating the sandbox temp dir.
     699             :   if (XRE_IsParentProcess()) {
     700             :     mContentProcessSandboxTempDir = CreateContentProcessSandboxTempDir();
     701             :     mContentTempDir = mContentProcessSandboxTempDir;
     702             :   } else {
     703             :     mContentTempDir = GetContentProcessSandboxTempDir();
     704             :   }
     705             : 
     706             :   if (!mContentTempDir) {
     707             :     nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR,
     708             :                                          getter_AddRefs(mContentTempDir));
     709             :     if (NS_WARN_IF(NS_FAILED(rv))) {
     710             :       return rv;
     711             :     }
     712             :   }
     713             : 
     714             : #if defined(XP_WIN)
     715             :   // The content temp dir can be used in sandbox rules, so we need to make sure
     716             :   // it doesn't contain any junction points or symlinks or the sandbox will
     717             :   // reject those rules.
     718             :   if (!mozilla::widget::WinUtils::ResolveJunctionPointsAndSymLinks(mContentTempDir)) {
     719             :     NS_WARNING("Failed to resolve Content Temp Dir.");
     720             :   }
     721             : #endif
     722             : 
     723             :   return NS_OK;
     724             : }
     725             : 
     726             : static bool
     727             : IsContentSandboxDisabled()
     728             : {
     729             :   return !BrowserTabsRemoteAutostart() || (GetEffectiveContentSandboxLevel() < 1);
     730             : }
     731             : 
     732             : //
     733             : // If a content process sandbox temp dir is to be used, returns an nsIFile
     734             : // for the directory. Returns null if the content sandbox is disabled or
     735             : // an error occurs.
     736             : //
     737             : static already_AddRefed<nsIFile>
     738             : GetContentProcessSandboxTempDir()
     739             : {
     740             :   if (IsContentSandboxDisabled()) {
     741             :     return nullptr;
     742             :   }
     743             : 
     744             :   nsCOMPtr<nsIFile> localFile;
     745             : 
     746             :   nsresult rv = NS_GetSpecialDirectory(GetContentProcessTempBaseDirKey(),
     747             :                                        getter_AddRefs(localFile));
     748             :   if (NS_WARN_IF(NS_FAILED(rv))) {
     749             :     return nullptr;
     750             :   }
     751             : 
     752             :   nsAutoString tempDirSuffix;
     753             :   rv = Preferences::GetString("security.sandbox.content.tempDirSuffix",
     754             :                               &tempDirSuffix);
     755             :   if (NS_WARN_IF(NS_FAILED(rv)) || tempDirSuffix.IsEmpty()) {
     756             :     return nullptr;
     757             :   }
     758             : 
     759             :   rv = localFile->Append(NS_LITERAL_STRING("Temp-") + tempDirSuffix);
     760             :   if (NS_WARN_IF(NS_FAILED(rv))) {
     761             :     return nullptr;
     762             :   }
     763             : 
     764             :   return localFile.forget();
     765             : }
     766             : 
     767             : //
     768             : // Create a temporary directory for use from sandboxed content processes.
     769             : // Only called in the parent. The path is derived from a UUID stored in a
     770             : // pref which is available to content processes. Returns null if the
     771             : // content sandbox is disabled or if an error occurs.
     772             : //
     773             : static already_AddRefed<nsIFile>
     774             : CreateContentProcessSandboxTempDir()
     775             : {
     776             :   if (IsContentSandboxDisabled()) {
     777             :     return nullptr;
     778             :   }
     779             : 
     780             :   // Get (and create if blank) temp directory suffix pref.
     781             :   nsresult rv;
     782             :   nsAdoptingString tempDirSuffix =
     783             :     Preferences::GetString("security.sandbox.content.tempDirSuffix");
     784             :   if (tempDirSuffix.IsEmpty()) {
     785             :     nsCOMPtr<nsIUUIDGenerator> uuidgen =
     786             :       do_GetService("@mozilla.org/uuid-generator;1", &rv);
     787             :     if (NS_WARN_IF(NS_FAILED(rv))) {
     788             :       return nullptr;
     789             :     }
     790             : 
     791             :     nsID uuid;
     792             :     rv = uuidgen->GenerateUUIDInPlace(&uuid);
     793             :     if (NS_WARN_IF(NS_FAILED(rv))) {
     794             :       return nullptr;
     795             :     }
     796             : 
     797             :     char uuidChars[NSID_LENGTH];
     798             :     uuid.ToProvidedString(uuidChars);
     799             :     tempDirSuffix.AssignASCII(uuidChars);
     800             : 
     801             :     // Save the pref
     802             :     rv = Preferences::SetCString("security.sandbox.content.tempDirSuffix",
     803             :                                  uuidChars);
     804             :     if (NS_WARN_IF(NS_FAILED(rv))) {
     805             :       // If we fail to save the pref we don't want to create the temp dir,
     806             :       // because we won't be able to clean it up later.
     807             :       return nullptr;
     808             :     }
     809             : 
     810             :     nsCOMPtr<nsIPrefService> prefsvc = Preferences::GetService();
     811             :     if (!prefsvc || NS_FAILED((rv = prefsvc->SavePrefFile(nullptr)))) {
     812             :       // Again, if we fail to save the pref file we might not be able to clean
     813             :       // up the temp directory, so don't create one.  Note that in the case
     814             :       // the preference values allows an off main thread save, the successful
     815             :       // return from the call doesn't mean we actually saved the file.  See
     816             :       // bug 1364496 for details.
     817             :       NS_WARNING("Failed to save pref file, cannot create temp dir.");
     818             :       return nullptr;
     819             :     }
     820             :   }
     821             : 
     822             :   nsCOMPtr<nsIFile> sandboxTempDir = GetContentProcessSandboxTempDir();
     823             :   if (!sandboxTempDir) {
     824             :     NS_WARNING("Failed to determine sandbox temp dir path.");
     825             :     return nullptr;
     826             :   }
     827             : 
     828             :   // Remove the directory. It may exist due to a previous crash.
     829             :   if (NS_FAILED(DeleteDirIfExists(sandboxTempDir))) {
     830             :     NS_WARNING("Failed to reset sandbox temp dir.");
     831             :     return nullptr;
     832             :   }
     833             : 
     834             :   // Create the directory
     835             :   rv = sandboxTempDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
     836             :   if (NS_FAILED(rv)) {
     837             :     NS_WARNING("Failed to create sandbox temp dir.");
     838             :     return nullptr;
     839             :   }
     840             : 
     841             :   return sandboxTempDir.forget();
     842             : }
     843             : 
     844             : static nsresult
     845             : DeleteDirIfExists(nsIFile* dir)
     846             : {
     847             :   if (dir) {
     848             :     // Don't return an error if the directory doesn't exist.
     849             :     // Windows Remove() returns NS_ERROR_FILE_NOT_FOUND while
     850             :     // OS X returns NS_ERROR_FILE_TARGET_DOES_NOT_EXIST.
     851             :     nsresult rv = dir->Remove(/* aRecursive */ true);
     852             :     if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND &&
     853             :         rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) {
     854             :       return rv;
     855             :     }
     856             :   }
     857             :   return NS_OK;
     858             : }
     859             : 
     860             : #endif // (defined(XP_WIN) || defined(XP_MACOSX)) &&
     861             :   // defined(MOZ_CONTENT_SANDBOX)
     862             : 
     863             : #ifdef MOZ_B2G
     864             : void
     865             : nsXREDirProvider::LoadAppBundleDirs()
     866             : {
     867             :   nsCOMPtr<nsIFile> dir;
     868             :   bool persistent = false;
     869             :   nsresult rv = GetFile(XRE_APP_DISTRIBUTION_DIR, &persistent, getter_AddRefs(dir));
     870             :   if (NS_FAILED(rv))
     871             :     return;
     872             : 
     873             :   dir->AppendNative(NS_LITERAL_CSTRING("bundles"));
     874             : 
     875             :   nsCOMPtr<nsISimpleEnumerator> e;
     876             :   rv = dir->GetDirectoryEntries(getter_AddRefs(e));
     877             :   if (NS_FAILED(rv))
     878             :     return;
     879             : 
     880             :   nsCOMPtr<nsIDirectoryEnumerator> files = do_QueryInterface(e);
     881             :   if (!files)
     882             :     return;
     883             : 
     884             :   nsCOMPtr<nsIFile> subdir;
     885             :   while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(subdir))) && subdir) {
     886             :     mAppBundleDirectories.AppendObject(subdir);
     887             : 
     888             :     nsCOMPtr<nsIFile> manifest =
     889             :       CloneAndAppend(subdir, "chrome.manifest");
     890             :     XRE_AddManifestLocation(NS_APP_LOCATION, manifest);
     891             :   }
     892             : }
     893             : #endif
     894             : 
     895             : static const char *const kAppendPrefDir[] = { "defaults", "preferences", nullptr };
     896             : 
     897             : #ifdef DEBUG_bsmedberg
     898             : static void
     899             : DumpFileArray(const char *key,
     900             :               nsCOMArray<nsIFile> dirs)
     901             : {
     902             :   fprintf(stderr, "nsXREDirProvider::GetFilesInternal(%s)\n", key);
     903             : 
     904             :   nsAutoCString path;
     905             :   for (int32_t i = 0; i < dirs.Count(); ++i) {
     906             :     dirs[i]->GetNativePath(path);
     907             :     fprintf(stderr, "  %s\n", path.get());
     908             :   }
     909             : }
     910             : #endif // DEBUG_bsmedberg
     911             : 
     912             : nsresult
     913          20 : nsXREDirProvider::GetFilesInternal(const char* aProperty,
     914             :                                    nsISimpleEnumerator** aResult)
     915             : {
     916          20 :   nsresult rv = NS_OK;
     917          20 :   *aResult = nullptr;
     918             : 
     919          20 :   if (!strcmp(aProperty, XRE_EXTENSIONS_DIR_LIST)) {
     920           2 :     nsCOMArray<nsIFile> directories;
     921             : 
     922             :     static const char *const kAppendNothing[] = { nullptr };
     923             : 
     924           1 :     LoadDirsIntoArray(mAppBundleDirectories,
     925           1 :                       kAppendNothing, directories);
     926           1 :     LoadDirsIntoArray(AddonManagerStartup::GetSingleton().ExtensionPaths(),
     927           1 :                       kAppendNothing, directories);
     928             : 
     929           1 :     rv = NS_NewArrayEnumerator(aResult, directories);
     930             :   }
     931          19 :   else if (!strcmp(aProperty, NS_APP_PREFS_DEFAULTS_DIR_LIST)) {
     932           6 :     nsCOMArray<nsIFile> directories;
     933             : 
     934           3 :     LoadDirIntoArray(mXULAppDir, kAppendPrefDir, directories);
     935           3 :     LoadDirsIntoArray(mAppBundleDirectories,
     936           3 :                       kAppendPrefDir, directories);
     937             : 
     938           3 :     rv = NS_NewArrayEnumerator(aResult, directories);
     939             :   }
     940          16 :   else if (!strcmp(aProperty, NS_EXT_PREFS_DEFAULTS_DIR_LIST)) {
     941           8 :     nsCOMArray<nsIFile> directories;
     942             : 
     943           4 :     LoadDirsIntoArray(AddonManagerStartup::GetSingleton().ExtensionPaths(),
     944           4 :                       kAppendPrefDir, directories);
     945             : 
     946           4 :     if (mProfileDir) {
     947           4 :       nsCOMPtr<nsIFile> overrideFile;
     948           2 :       mProfileDir->Clone(getter_AddRefs(overrideFile));
     949           2 :       overrideFile->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));
     950             : 
     951             :       bool exists;
     952           2 :       if (NS_SUCCEEDED(overrideFile->Exists(&exists)) && exists)
     953           0 :         directories.AppendObject(overrideFile);
     954             :     }
     955             : 
     956           4 :     rv = NS_NewArrayEnumerator(aResult, directories);
     957             :   }
     958          12 :   else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) {
     959             :     // NS_APP_CHROME_DIR_LIST is only used to get default (native) icons
     960             :     // for OS window decoration.
     961             : 
     962             :     static const char *const kAppendChromeDir[] = { "chrome", nullptr };
     963          20 :     nsCOMArray<nsIFile> directories;
     964          10 :     LoadDirIntoArray(mXULAppDir,
     965             :                      kAppendChromeDir,
     966          10 :                      directories);
     967          10 :     LoadDirsIntoArray(mAppBundleDirectories,
     968             :                       kAppendChromeDir,
     969          10 :                       directories);
     970          10 :     LoadDirsIntoArray(AddonManagerStartup::GetSingleton().ExtensionPaths(),
     971             :                       kAppendChromeDir,
     972          10 :                       directories);
     973             : 
     974          10 :     rv = NS_NewArrayEnumerator(aResult, directories);
     975             :   }
     976           2 :   else if (!strcmp(aProperty, NS_APP_PLUGINS_DIR_LIST)) {
     977           2 :     nsCOMArray<nsIFile> directories;
     978             : 
     979           1 :     if (mozilla::Preferences::GetBool("plugins.load_appdir_plugins", false)) {
     980           0 :       nsCOMPtr<nsIFile> appdir;
     981           0 :       rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(appdir));
     982           0 :       if (NS_SUCCEEDED(rv)) {
     983           0 :         appdir->SetNativeLeafName(NS_LITERAL_CSTRING("plugins"));
     984           0 :         directories.AppendObject(appdir);
     985             :       }
     986             :     }
     987             : 
     988             :     static const char *const kAppendPlugins[] = { "plugins", nullptr };
     989             : 
     990             :     // The root dirserviceprovider does quite a bit for us: we're mainly
     991             :     // interested in xulapp and extension-provided plugins.
     992           1 :     LoadDirsIntoArray(mAppBundleDirectories,
     993             :                       kAppendPlugins,
     994           1 :                       directories);
     995           1 :     LoadDirsIntoArray(AddonManagerStartup::GetSingleton().ExtensionPaths(),
     996             :                       kAppendPlugins,
     997           1 :                       directories);
     998             : 
     999           1 :     if (mProfileDir) {
    1000           2 :       nsCOMArray<nsIFile> profileDir;
    1001           1 :       profileDir.AppendObject(mProfileDir);
    1002             :       LoadDirsIntoArray(profileDir,
    1003             :                         kAppendPlugins,
    1004           1 :                         directories);
    1005             :     }
    1006             : 
    1007           1 :     rv = NS_NewArrayEnumerator(aResult, directories);
    1008           1 :     NS_ENSURE_SUCCESS(rv, rv);
    1009             : 
    1010           1 :     rv = NS_SUCCESS_AGGREGATE_RESULT;
    1011             :   }
    1012             :   else
    1013           1 :     rv = NS_ERROR_FAILURE;
    1014             : 
    1015          20 :   return rv;
    1016             : }
    1017             : 
    1018             : NS_IMETHODIMP
    1019           0 : nsXREDirProvider::GetDirectory(nsIFile* *aResult)
    1020             : {
    1021           0 :   NS_ENSURE_TRUE(mProfileDir, NS_ERROR_NOT_INITIALIZED);
    1022             : 
    1023           0 :   return mProfileDir->Clone(aResult);
    1024             : }
    1025             : 
    1026             : NS_IMETHODIMP
    1027           1 : nsXREDirProvider::DoStartup()
    1028             : {
    1029           1 :   if (!mProfileNotified) {
    1030             :     nsCOMPtr<nsIObserverService> obsSvc =
    1031           2 :       mozilla::services::GetObserverService();
    1032           1 :     if (!obsSvc) return NS_ERROR_FAILURE;
    1033             : 
    1034           1 :     mProfileNotified = true;
    1035             : 
    1036             :     /*
    1037             :        Setup prefs before profile-do-change to be able to use them to track
    1038             :        crashes and because we want to begin crash tracking before other code run
    1039             :        from this notification since they may cause crashes.
    1040             :     */
    1041           1 :     nsresult rv = mozilla::Preferences::ResetAndReadUserPrefs();
    1042           1 :     if (NS_FAILED(rv)) NS_WARNING("Failed to setup pref service.");
    1043             : 
    1044           1 :     bool safeModeNecessary = false;
    1045           2 :     nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
    1046           1 :     if (appStartup) {
    1047           1 :       rv = appStartup->TrackStartupCrashBegin(&safeModeNecessary);
    1048           1 :       if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE)
    1049           0 :         NS_WARNING("Error while beginning startup crash tracking");
    1050             : 
    1051           1 :       if (!gSafeMode && safeModeNecessary) {
    1052           0 :         appStartup->RestartInSafeMode(nsIAppStartup::eForceQuit);
    1053           0 :         return NS_OK;
    1054             :       }
    1055             :     }
    1056             : 
    1057             :     static const char16_t kStartup[] = {'s','t','a','r','t','u','p','\0'};
    1058           1 :     obsSvc->NotifyObservers(nullptr, "profile-do-change", kStartup);
    1059             : 
    1060             :     // Init the Extension Manager
    1061           2 :     nsCOMPtr<nsIObserver> em = do_GetService("@mozilla.org/addons/integration;1");
    1062           1 :     if (em) {
    1063           1 :       em->Observe(nullptr, "addons-startup", nullptr);
    1064             :     } else {
    1065           0 :       NS_WARNING("Failed to create Addons Manager.");
    1066             :     }
    1067             : 
    1068           1 :     obsSvc->NotifyObservers(nullptr, "load-extension-defaults", nullptr);
    1069           1 :     obsSvc->NotifyObservers(nullptr, "profile-after-change", kStartup);
    1070             : 
    1071             :     // Any component that has registered for the profile-after-change category
    1072             :     // should also be created at this time.
    1073             :     (void)NS_CreateServicesFromCategory("profile-after-change", nullptr,
    1074           1 :                                         "profile-after-change");
    1075             : 
    1076           1 :     if (gSafeMode && safeModeNecessary) {
    1077             :       static const char16_t kCrashed[] = {'c','r','a','s','h','e','d','\0'};
    1078           0 :       obsSvc->NotifyObservers(nullptr, "safemode-forced", kCrashed);
    1079             :     }
    1080             : 
    1081             :     // 1 = Regular mode, 2 = Safe mode, 3 = Safe mode forced
    1082           1 :     int mode = 1;
    1083           1 :     if (gSafeMode) {
    1084           0 :       if (safeModeNecessary)
    1085           0 :         mode = 3;
    1086             :       else
    1087           0 :         mode = 2;
    1088             :     }
    1089           1 :     mozilla::Telemetry::Accumulate(mozilla::Telemetry::SAFE_MODE_USAGE, mode);
    1090             : 
    1091             :     // Telemetry about number of profiles.
    1092             :     nsCOMPtr<nsIToolkitProfileService> profileService =
    1093           2 :       do_GetService("@mozilla.org/toolkit/profile-service;1");
    1094           1 :     if (profileService) {
    1095           2 :       nsCOMPtr<nsISimpleEnumerator> profiles;
    1096           1 :       rv = profileService->GetProfiles(getter_AddRefs(profiles));
    1097           1 :       if (NS_WARN_IF(NS_FAILED(rv))) {
    1098           0 :         return rv;
    1099             :       }
    1100             : 
    1101           1 :       uint32_t count = 0;
    1102           2 :       nsCOMPtr<nsISupports> profile;
    1103           3 :       while (NS_SUCCEEDED(profiles->GetNext(getter_AddRefs(profile)))) {
    1104           1 :         ++count;
    1105             :       }
    1106             : 
    1107             :       mozilla::Telemetry::Accumulate(mozilla::Telemetry::NUMBER_OF_PROFILES,
    1108           1 :                                      count);
    1109             :     }
    1110             : 
    1111           1 :     obsSvc->NotifyObservers(nullptr, "profile-initial-state", nullptr);
    1112             : 
    1113             : #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
    1114             :     // Makes sure the content temp dir has been loaded if it hasn't been
    1115             :     // already. In the parent this ensures it has been created before we attempt
    1116             :     // to start any content processes.
    1117             :     if (!mContentTempDir) {
    1118             :       mozilla::Unused << NS_WARN_IF(NS_FAILED(LoadContentProcessTempDir()));
    1119             :     }
    1120             : #endif
    1121             :   }
    1122           1 :   return NS_OK;
    1123             : }
    1124             : 
    1125             : void
    1126           0 : nsXREDirProvider::DoShutdown()
    1127             : {
    1128           0 :   AUTO_PROFILER_LABEL("nsXREDirProvider::DoShutdown", OTHER);
    1129             : 
    1130           0 :   if (mProfileNotified) {
    1131             :     nsCOMPtr<nsIObserverService> obsSvc =
    1132           0 :       mozilla::services::GetObserverService();
    1133           0 :     NS_ASSERTION(obsSvc, "No observer service?");
    1134           0 :     if (obsSvc) {
    1135             :       static const char16_t kShutdownPersist[] = u"shutdown-persist";
    1136           0 :       obsSvc->NotifyObservers(nullptr, "profile-change-net-teardown", kShutdownPersist);
    1137           0 :       obsSvc->NotifyObservers(nullptr, "profile-change-teardown", kShutdownPersist);
    1138           0 :       obsSvc->NotifyObservers(nullptr, "profile-before-change", kShutdownPersist);
    1139           0 :       obsSvc->NotifyObservers(nullptr, "profile-before-change-qm", kShutdownPersist);
    1140           0 :       obsSvc->NotifyObservers(nullptr, "profile-before-change-telemetry", kShutdownPersist);
    1141             :     }
    1142           0 :     mProfileNotified = false;
    1143             :   }
    1144             : 
    1145             : #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
    1146             :   if (XRE_IsParentProcess()) {
    1147             :     Unused << DeleteDirIfExists(mContentProcessSandboxTempDir);
    1148             :   }
    1149             : #endif
    1150           0 : }
    1151             : 
    1152             : #ifdef XP_WIN
    1153             : static nsresult
    1154             : GetShellFolderPath(KNOWNFOLDERID folder, nsAString& _retval)
    1155             : {
    1156             :   DWORD flags = KF_FLAG_SIMPLE_IDLIST | KF_FLAG_DONT_VERIFY | KF_FLAG_NO_ALIAS;
    1157             :   PWSTR path = nullptr;
    1158             : 
    1159             :   if (!SUCCEEDED(SHGetKnownFolderPath(folder, flags, NULL, &path))) {
    1160             :     return NS_ERROR_NOT_AVAILABLE;
    1161             :   }
    1162             : 
    1163             :   _retval = nsDependentString(path);
    1164             :   CoTaskMemFree(path);
    1165             :   return NS_OK;
    1166             : }
    1167             : 
    1168             : /**
    1169             :  * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
    1170             :  * querying the registry when the call to SHGetSpecialFolderLocation or
    1171             :  * SHGetPathFromIDListW is unable to provide these paths (Bug 513958).
    1172             :  */
    1173             : static nsresult
    1174             : GetRegWindowsAppDataFolder(bool aLocal, nsAString& _retval)
    1175             : {
    1176             :   HKEY key;
    1177             :   LPCWSTR keyName =
    1178             :     L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
    1179             :   DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName, 0, KEY_READ,
    1180             :                               &key);
    1181             :   if (res != ERROR_SUCCESS) {
    1182             :     _retval.SetLength(0);
    1183             :     return NS_ERROR_NOT_AVAILABLE;
    1184             :   }
    1185             : 
    1186             :   DWORD type, size;
    1187             :   res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
    1188             :                          nullptr, &type, nullptr, &size);
    1189             :   // The call to RegQueryValueExW must succeed, the type must be REG_SZ, the
    1190             :   // buffer size must not equal 0, and the buffer size be a multiple of 2.
    1191             :   if (res != ERROR_SUCCESS || type != REG_SZ || size == 0 || size % 2 != 0) {
    1192             :     ::RegCloseKey(key);
    1193             :     _retval.SetLength(0);
    1194             :     return NS_ERROR_NOT_AVAILABLE;
    1195             :   }
    1196             : 
    1197             :   // |size| may or may not include room for the terminating null character
    1198             :   DWORD resultLen = size / 2;
    1199             : 
    1200             :   if (!_retval.SetLength(resultLen, mozilla::fallible)) {
    1201             :     ::RegCloseKey(key);
    1202             :     _retval.SetLength(0);
    1203             :     return NS_ERROR_NOT_AVAILABLE;
    1204             :   }
    1205             : 
    1206             :   nsAString::iterator begin;
    1207             :   _retval.BeginWriting(begin);
    1208             : 
    1209             :   res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
    1210             :                          nullptr, nullptr, (LPBYTE) begin.get(), &size);
    1211             :   ::RegCloseKey(key);
    1212             :   if (res != ERROR_SUCCESS) {
    1213             :     _retval.SetLength(0);
    1214             :     return NS_ERROR_NOT_AVAILABLE;
    1215             :   }
    1216             : 
    1217             :   if (!_retval.CharAt(resultLen - 1)) {
    1218             :     // It was already null terminated.
    1219             :     _retval.Truncate(resultLen - 1);
    1220             :   }
    1221             : 
    1222             :   return NS_OK;
    1223             : }
    1224             : 
    1225             : static bool
    1226             : GetCachedHash(HKEY rootKey, const nsAString &regPath, const nsAString &path,
    1227             :               nsAString &cachedHash)
    1228             : {
    1229             :   HKEY baseKey;
    1230             :   if (RegOpenKeyExW(rootKey, reinterpret_cast<const wchar_t*>(regPath.BeginReading()), 0, KEY_READ, &baseKey) !=
    1231             :       ERROR_SUCCESS) {
    1232             :     return false;
    1233             :   }
    1234             : 
    1235             :   wchar_t cachedHashRaw[512];
    1236             :   DWORD bufferSize = sizeof(cachedHashRaw);
    1237             :   LONG result = RegQueryValueExW(baseKey, reinterpret_cast<const wchar_t*>(path.BeginReading()), 0, nullptr,
    1238             :                                  (LPBYTE)cachedHashRaw, &bufferSize);
    1239             :   RegCloseKey(baseKey);
    1240             :   if (result == ERROR_SUCCESS) {
    1241             :     cachedHash.Assign(cachedHashRaw);
    1242             :   }
    1243             :   return ERROR_SUCCESS == result;
    1244             : }
    1245             : 
    1246             : #endif
    1247             : 
    1248             : nsresult
    1249           2 : nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult)
    1250             : {
    1251           4 :   nsCOMPtr<nsIFile> updRoot;
    1252             : #if defined(MOZ_WIDGET_GONK)
    1253             : 
    1254             :   nsresult rv = NS_NewNativeLocalFile(nsDependentCString("/data/local"),
    1255             :                                       true,
    1256             :                                       getter_AddRefs(updRoot));
    1257             :   NS_ENSURE_SUCCESS(rv, rv);
    1258             : 
    1259             : #else
    1260           4 :   nsCOMPtr<nsIFile> appFile;
    1261           2 :   bool per = false;
    1262           2 :   nsresult rv = GetFile(XRE_EXECUTABLE_FILE, &per, getter_AddRefs(appFile));
    1263           2 :   NS_ENSURE_SUCCESS(rv, rv);
    1264           2 :   rv = appFile->GetParent(getter_AddRefs(updRoot));
    1265           2 :   NS_ENSURE_SUCCESS(rv, rv);
    1266             : 
    1267             : #ifdef XP_MACOSX
    1268             :   nsCOMPtr<nsIFile> appRootDirFile;
    1269             :   nsCOMPtr<nsIFile> localDir;
    1270             :   nsAutoString appDirPath;
    1271             :   if (NS_FAILED(appFile->GetParent(getter_AddRefs(appRootDirFile))) ||
    1272             :       NS_FAILED(appRootDirFile->GetPath(appDirPath)) ||
    1273             :       NS_FAILED(GetUserDataDirectoryHome(getter_AddRefs(localDir), true))) {
    1274             :     return NS_ERROR_FAILURE;
    1275             :   }
    1276             : 
    1277             :   int32_t dotIndex = appDirPath.RFind(".app");
    1278             :   if (dotIndex == kNotFound) {
    1279             :     dotIndex = appDirPath.Length();
    1280             :   }
    1281             :   appDirPath = Substring(appDirPath, 1, dotIndex - 1);
    1282             : 
    1283             :   bool hasVendor = gAppData->vendor && strlen(gAppData->vendor) != 0;
    1284             :   if (hasVendor || gAppData->name) {
    1285             :     if (NS_FAILED(localDir->AppendNative(nsDependentCString(hasVendor ?
    1286             :                                            gAppData->vendor :
    1287             :                                            gAppData->name)))) {
    1288             :       return NS_ERROR_FAILURE;
    1289             :     }
    1290             :   } else if (NS_FAILED(localDir->AppendNative(NS_LITERAL_CSTRING("Mozilla")))) {
    1291             :     return NS_ERROR_FAILURE;
    1292             :   }
    1293             : 
    1294             :   if (NS_FAILED(localDir->Append(NS_LITERAL_STRING("updates"))) ||
    1295             :       NS_FAILED(localDir->AppendRelativePath(appDirPath))) {
    1296             :     return NS_ERROR_FAILURE;
    1297             :   }
    1298             : 
    1299             :   localDir.forget(aResult);
    1300             :   return NS_OK;
    1301             : 
    1302             : #elif XP_WIN
    1303             :   nsAutoString pathHash;
    1304             :   bool pathHashResult = false;
    1305             :   bool hasVendor = gAppData->vendor && strlen(gAppData->vendor) != 0;
    1306             : 
    1307             :   nsAutoString appDirPath;
    1308             :   if (SUCCEEDED(updRoot->GetPath(appDirPath))) {
    1309             : 
    1310             :     // Figure out where we should check for a cached hash value. If the
    1311             :     // application doesn't have the nsXREAppData vendor value defined check
    1312             :     // under SOFTWARE\Mozilla.
    1313             :     wchar_t regPath[1024] = { L'\0' };
    1314             :     swprintf_s(regPath, mozilla::ArrayLength(regPath), L"SOFTWARE\\%S\\%S\\TaskBarIDs",
    1315             :                (hasVendor ? gAppData->vendor : "Mozilla"), MOZ_APP_BASENAME);
    1316             : 
    1317             :     // If we pre-computed the hash, grab it from the registry.
    1318             :     pathHashResult = GetCachedHash(HKEY_LOCAL_MACHINE,
    1319             :                                    nsDependentString(regPath), appDirPath,
    1320             :                                    pathHash);
    1321             :     if (!pathHashResult) {
    1322             :       pathHashResult = GetCachedHash(HKEY_CURRENT_USER,
    1323             :                                      nsDependentString(regPath), appDirPath,
    1324             :                                      pathHash);
    1325             :     }
    1326             :   }
    1327             : 
    1328             :   if (!pathHashResult) {
    1329             :     // This should only happen when the installer isn't used (e.g. zip builds).
    1330             :     uint64_t hash = CityHash64(static_cast<const char *>(appDirPath.get()),
    1331             :                                appDirPath.Length() * sizeof(nsAutoString::char_type));
    1332             :     pathHash.AppendInt((int)(hash >> 32), 16);
    1333             :     pathHash.AppendInt((int)hash, 16);
    1334             :     // The installer implementation writes the registry values that were checked
    1335             :     // in the previous block for this value in uppercase and since it is an
    1336             :     // option to have a case sensitive file system on Windows this value must
    1337             :     // also be in uppercase.
    1338             :     ToUpperCase(pathHash);
    1339             :   }
    1340             : 
    1341             :   // As a last ditch effort, get the local app data directory and if a vendor
    1342             :   // name exists append it. If only a product name exists, append it. If neither
    1343             :   // exist fallback to old handling. We don't use the product name on purpose
    1344             :   // because we want a shared update directory for different apps run from the
    1345             :   // same path.
    1346             :   nsCOMPtr<nsIFile> localDir;
    1347             :   if ((hasVendor || gAppData->name) &&
    1348             :       NS_SUCCEEDED(GetUserDataDirectoryHome(getter_AddRefs(localDir), true)) &&
    1349             :       NS_SUCCEEDED(localDir->AppendNative(nsDependentCString(hasVendor ?
    1350             :                                           gAppData->vendor : gAppData->name))) &&
    1351             :       NS_SUCCEEDED(localDir->Append(NS_LITERAL_STRING("updates"))) &&
    1352             :       NS_SUCCEEDED(localDir->Append(pathHash))) {
    1353             :     localDir.forget(aResult);
    1354             :     return NS_OK;
    1355             :   }
    1356             : 
    1357             :   nsAutoString appPath;
    1358             :   rv = updRoot->GetPath(appPath);
    1359             :   NS_ENSURE_SUCCESS(rv, rv);
    1360             : 
    1361             :   // AppDir may be a short path. Convert to long path to make sure
    1362             :   // the consistency of the update folder location
    1363             :   nsString longPath;
    1364             :   wchar_t* buf;
    1365             : 
    1366             :   uint32_t bufLength = longPath.GetMutableData(&buf, MAXPATHLEN);
    1367             :   NS_ENSURE_TRUE(bufLength >= MAXPATHLEN, NS_ERROR_OUT_OF_MEMORY);
    1368             : 
    1369             :   DWORD len = GetLongPathNameW(appPath.get(), buf, bufLength);
    1370             : 
    1371             :   // Failing GetLongPathName() is not fatal.
    1372             :   if (len <= 0 || len >= bufLength)
    1373             :     longPath.Assign(appPath);
    1374             :   else
    1375             :     longPath.SetLength(len);
    1376             : 
    1377             :   // Use <UserLocalDataDir>\updates\<relative path to app dir from
    1378             :   // Program Files> if app dir is under Program Files to avoid the
    1379             :   // folder virtualization mess on Windows Vista
    1380             :   nsAutoString programFiles;
    1381             :   rv = GetShellFolderPath(FOLDERID_ProgramFiles, programFiles);
    1382             :   NS_ENSURE_SUCCESS(rv, rv);
    1383             : 
    1384             :   programFiles.Append('\\');
    1385             :   uint32_t programFilesLen = programFiles.Length();
    1386             : 
    1387             :   nsAutoString programName;
    1388             :   if (_wcsnicmp(programFiles.get(), longPath.get(), programFilesLen) == 0) {
    1389             :     programName = Substring(longPath, programFilesLen);
    1390             :   } else {
    1391             :     // We need the update root directory to live outside of the installation
    1392             :     // directory, because otherwise the updater writing the log file can cause
    1393             :     // the directory to be locked, which prevents it from being replaced after
    1394             :     // background updates.
    1395             :     programName.AssignASCII(MOZ_APP_NAME);
    1396             :   }
    1397             : 
    1398             :   rv = GetUserLocalDataDirectory(getter_AddRefs(updRoot));
    1399             :   NS_ENSURE_SUCCESS(rv, rv);
    1400             : 
    1401             :   rv = updRoot->AppendRelativePath(programName);
    1402             :   NS_ENSURE_SUCCESS(rv, rv);
    1403             : 
    1404             : #endif // XP_WIN
    1405             : #endif
    1406           2 :   updRoot.forget(aResult);
    1407           2 :   return NS_OK;
    1408             : }
    1409             : 
    1410             : nsresult
    1411          20 : nsXREDirProvider::GetProfileStartupDir(nsIFile* *aResult)
    1412             : {
    1413          20 :   if (mProfileDir)
    1414          15 :     return mProfileDir->Clone(aResult);
    1415             : 
    1416           5 :   if (mAppProvider) {
    1417           0 :     nsCOMPtr<nsIFile> needsclone;
    1418             :     bool dummy;
    1419           0 :     nsresult rv = mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP,
    1420             :                                         &dummy,
    1421           0 :                                         getter_AddRefs(needsclone));
    1422           0 :     if (NS_SUCCEEDED(rv))
    1423           0 :       return needsclone->Clone(aResult);
    1424             :   }
    1425             : 
    1426           5 :   return NS_ERROR_FAILURE;
    1427             : }
    1428             : 
    1429             : nsresult
    1430          19 : nsXREDirProvider::GetProfileDir(nsIFile* *aResult)
    1431             : {
    1432          19 :   if (mProfileDir) {
    1433          14 :     if (!mProfileNotified)
    1434           2 :       return NS_ERROR_FAILURE;
    1435             : 
    1436          12 :     return mProfileDir->Clone(aResult);
    1437             :   }
    1438             : 
    1439           5 :   if (mAppProvider) {
    1440           0 :     nsCOMPtr<nsIFile> needsclone;
    1441             :     bool dummy;
    1442           0 :     nsresult rv = mAppProvider->GetFile(NS_APP_USER_PROFILE_50_DIR,
    1443             :                                         &dummy,
    1444           0 :                                         getter_AddRefs(needsclone));
    1445           0 :     if (NS_SUCCEEDED(rv))
    1446           0 :       return needsclone->Clone(aResult);
    1447             :   }
    1448             : 
    1449           5 :   return NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, aResult);
    1450             : }
    1451             : 
    1452             : nsresult
    1453           5 : nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal)
    1454             : {
    1455             :   // Copied from nsAppFileLocationProvider (more or less)
    1456             :   nsresult rv;
    1457          10 :   nsCOMPtr<nsIFile> localDir;
    1458             : 
    1459             : #if defined(XP_MACOSX)
    1460             :   FSRef fsRef;
    1461             :   OSType folderType;
    1462             :   if (aLocal) {
    1463             :     folderType = kCachedDataFolderType;
    1464             :   } else {
    1465             : #ifdef MOZ_THUNDERBIRD
    1466             :     folderType = kDomainLibraryFolderType;
    1467             : #else
    1468             :     folderType = kApplicationSupportFolderType;
    1469             : #endif
    1470             :   }
    1471             :   OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef);
    1472             :   NS_ENSURE_FALSE(err, NS_ERROR_FAILURE);
    1473             : 
    1474             :   rv = NS_NewNativeLocalFile(EmptyCString(), true, getter_AddRefs(localDir));
    1475             :   NS_ENSURE_SUCCESS(rv, rv);
    1476             : 
    1477             :   nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(localDir);
    1478             :   NS_ENSURE_TRUE(dirFileMac, NS_ERROR_UNEXPECTED);
    1479             : 
    1480             :   rv = dirFileMac->InitWithFSRef(&fsRef);
    1481             :   NS_ENSURE_SUCCESS(rv, rv);
    1482             : 
    1483             :   localDir = do_QueryInterface(dirFileMac, &rv);
    1484             : #elif defined(XP_IOS)
    1485             :   nsAutoCString userDir;
    1486             :   if (GetUIKitDirectory(aLocal, userDir)) {
    1487             :     rv = NS_NewNativeLocalFile(userDir, true, getter_AddRefs(localDir));
    1488             :   } else {
    1489             :     rv = NS_ERROR_FAILURE;
    1490             :   }
    1491             :   NS_ENSURE_SUCCESS(rv, rv);
    1492             : #elif defined(XP_WIN)
    1493             :   nsString path;
    1494             :   if (aLocal) {
    1495             :     rv = GetShellFolderPath(FOLDERID_LocalAppData, path);
    1496             :     if (NS_FAILED(rv))
    1497             :       rv = GetRegWindowsAppDataFolder(aLocal, path);
    1498             :   }
    1499             :   if (!aLocal || NS_FAILED(rv)) {
    1500             :     rv = GetShellFolderPath(FOLDERID_RoamingAppData, path);
    1501             :     if (NS_FAILED(rv)) {
    1502             :       if (!aLocal)
    1503             :         rv = GetRegWindowsAppDataFolder(aLocal, path);
    1504             :     }
    1505             :   }
    1506             :   NS_ENSURE_SUCCESS(rv, rv);
    1507             : 
    1508             :   rv = NS_NewLocalFile(path, true, getter_AddRefs(localDir));
    1509             : #elif defined(MOZ_WIDGET_GONK)
    1510             :   rv = NS_NewNativeLocalFile(NS_LITERAL_CSTRING("/data/b2g"), true,
    1511             :                              getter_AddRefs(localDir));
    1512             : #elif defined(XP_UNIX)
    1513           5 :   const char* homeDir = getenv("HOME");
    1514           5 :   if (!homeDir || !*homeDir)
    1515           0 :     return NS_ERROR_FAILURE;
    1516             : 
    1517             : #ifdef ANDROID /* We want (ProfD == ProfLD) on Android. */
    1518             :   aLocal = false;
    1519             : #endif
    1520             : 
    1521           5 :   if (aLocal) {
    1522             :     // If $XDG_CACHE_HOME is defined use it, otherwise use $HOME/.cache.
    1523           1 :     const char* cacheHome = getenv("XDG_CACHE_HOME");
    1524           1 :     if (cacheHome && *cacheHome) {
    1525           0 :       rv = NS_NewNativeLocalFile(nsDependentCString(cacheHome), true,
    1526           0 :                                  getter_AddRefs(localDir));
    1527             :     } else {
    1528           2 :       rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
    1529           3 :                                  getter_AddRefs(localDir));
    1530           1 :       if (NS_SUCCEEDED(rv))
    1531           1 :         rv = localDir->AppendNative(NS_LITERAL_CSTRING(".cache"));
    1532             :     }
    1533             :   } else {
    1534           8 :     rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
    1535          12 :                                getter_AddRefs(localDir));
    1536             :   }
    1537             : #else
    1538             : #error "Don't know how to get product dir on your platform"
    1539             : #endif
    1540             : 
    1541           5 :   NS_IF_ADDREF(*aFile = localDir);
    1542           5 :   return rv;
    1543             : }
    1544             : 
    1545             : nsresult
    1546           0 : nsXREDirProvider::GetSysUserExtensionsDirectory(nsIFile** aFile)
    1547             : {
    1548           0 :   nsCOMPtr<nsIFile> localDir;
    1549           0 :   nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), false);
    1550           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1551             : 
    1552           0 :   rv = AppendSysUserExtensionPath(localDir);
    1553           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1554             : 
    1555           0 :   rv = EnsureDirectoryExists(localDir);
    1556           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1557             : 
    1558           0 :   localDir.forget(aFile);
    1559           0 :   return NS_OK;
    1560             : }
    1561             : 
    1562             : #if defined(XP_UNIX) || defined(XP_MACOSX)
    1563             : nsresult
    1564           0 : nsXREDirProvider::GetSystemExtensionsDirectory(nsIFile** aFile)
    1565             : {
    1566             :   nsresult rv;
    1567           0 :   nsCOMPtr<nsIFile> localDir;
    1568             : 
    1569           0 :   rv = GetSystemParentDirectory(getter_AddRefs(localDir));
    1570           0 :   if (NS_SUCCEEDED(rv)) {
    1571           0 :     NS_NAMED_LITERAL_CSTRING(sExtensions,
    1572             : #if defined(XP_MACOSX)
    1573             :                              "Extensions"
    1574             : #else
    1575             :                              "extensions"
    1576             : #endif
    1577             :                              );
    1578             : 
    1579           0 :     rv = localDir->AppendNative(sExtensions);
    1580           0 :     if (NS_SUCCEEDED(rv)) {
    1581           0 :       localDir.forget(aFile);
    1582             :     }
    1583             :   }
    1584           0 :   return rv;
    1585             : }
    1586             : #endif
    1587             : 
    1588             : nsresult
    1589           5 : nsXREDirProvider::GetUserDataDirectory(nsIFile** aFile, bool aLocal,
    1590             :                                        const nsACString* aProfileName,
    1591             :                                        const nsACString* aAppName,
    1592             :                                        const nsACString* aVendorName)
    1593             : {
    1594          10 :   nsCOMPtr<nsIFile> localDir;
    1595           5 :   nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), aLocal);
    1596           5 :   NS_ENSURE_SUCCESS(rv, rv);
    1597             : 
    1598           5 :   rv = AppendProfilePath(localDir, aProfileName, aAppName, aVendorName, aLocal);
    1599           5 :   NS_ENSURE_SUCCESS(rv, rv);
    1600             : 
    1601             : #ifdef DEBUG_jungshik
    1602             :   nsAutoCString cwd;
    1603             :   localDir->GetNativePath(cwd);
    1604             :   printf("nsXREDirProvider::GetUserDataDirectory: %s\n", cwd.get());
    1605             : #endif
    1606           5 :   rv = EnsureDirectoryExists(localDir);
    1607           5 :   NS_ENSURE_SUCCESS(rv, rv);
    1608             : 
    1609           5 :   localDir.forget(aFile);
    1610           5 :   return NS_OK;
    1611             : }
    1612             : 
    1613             : nsresult
    1614           7 : nsXREDirProvider::EnsureDirectoryExists(nsIFile* aDirectory)
    1615             : {
    1616             :   bool exists;
    1617           7 :   nsresult rv = aDirectory->Exists(&exists);
    1618           7 :   NS_ENSURE_SUCCESS(rv, rv);
    1619             : #ifdef DEBUG_jungshik
    1620             :   if (!exists) {
    1621             :     nsAutoCString cwd;
    1622             :     aDirectory->GetNativePath(cwd);
    1623             :     printf("nsXREDirProvider::EnsureDirectoryExists: %s does not\n", cwd.get());
    1624             :   }
    1625             : #endif
    1626           7 :   if (!exists)
    1627           0 :     rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0700);
    1628             : #ifdef DEBUG_jungshik
    1629             :   if (NS_FAILED(rv))
    1630             :     NS_WARNING("nsXREDirProvider::EnsureDirectoryExists: create failed");
    1631             : #endif
    1632             : 
    1633           7 :   return rv;
    1634             : }
    1635             : 
    1636             : nsresult
    1637           0 : nsXREDirProvider::AppendSysUserExtensionPath(nsIFile* aFile)
    1638             : {
    1639           0 :   NS_ASSERTION(aFile, "Null pointer!");
    1640             : 
    1641             :   nsresult rv;
    1642             : 
    1643             : #if defined (XP_MACOSX) || defined(XP_WIN)
    1644             : 
    1645             :   static const char* const sXR = "Mozilla";
    1646             :   rv = aFile->AppendNative(nsDependentCString(sXR));
    1647             :   NS_ENSURE_SUCCESS(rv, rv);
    1648             : 
    1649             :   static const char* const sExtensions = "Extensions";
    1650             :   rv = aFile->AppendNative(nsDependentCString(sExtensions));
    1651             :   NS_ENSURE_SUCCESS(rv, rv);
    1652             : 
    1653             : #elif defined(XP_UNIX)
    1654             : 
    1655             :   static const char* const sXR = ".mozilla";
    1656           0 :   rv = aFile->AppendNative(nsDependentCString(sXR));
    1657           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1658             : 
    1659             :   static const char* const sExtensions = "extensions";
    1660           0 :   rv = aFile->AppendNative(nsDependentCString(sExtensions));
    1661           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1662             : 
    1663             : #else
    1664             : #error "Don't know how to get XRE user extension path on your platform"
    1665             : #endif
    1666           0 :   return NS_OK;
    1667             : }
    1668             : 
    1669             : 
    1670             : nsresult
    1671           5 : nsXREDirProvider::AppendProfilePath(nsIFile* aFile,
    1672             :                                     const nsACString* aProfileName,
    1673             :                                     const nsACString* aAppName,
    1674             :                                     const nsACString* aVendorName,
    1675             :                                     bool aLocal)
    1676             : {
    1677           5 :   NS_ASSERTION(aFile, "Null pointer!");
    1678             : 
    1679           5 :   if (!gAppData) {
    1680           0 :     return NS_ERROR_FAILURE;
    1681             :   }
    1682             : 
    1683          10 :   nsAutoCString profile;
    1684          10 :   nsAutoCString appName;
    1685          10 :   nsAutoCString vendor;
    1686           5 :   if (aProfileName && !aProfileName->IsEmpty()) {
    1687           0 :     profile = *aProfileName;
    1688           5 :   } else if (aAppName) {
    1689           0 :     appName = *aAppName;
    1690           0 :     if (aVendorName) {
    1691           0 :       vendor = *aVendorName;
    1692             :     }
    1693           5 :   } else if (gAppData->profile) {
    1694           0 :     profile = gAppData->profile;
    1695             :   } else {
    1696           5 :     appName = gAppData->name;
    1697           5 :     vendor = gAppData->vendor;
    1698             :   }
    1699             : 
    1700             :   nsresult rv;
    1701             : 
    1702             : #if defined (XP_MACOSX)
    1703             :   if (!profile.IsEmpty()) {
    1704             :     rv = AppendProfileString(aFile, profile.get());
    1705             :   }
    1706             :   else {
    1707             :     // Note that MacOS ignores the vendor when creating the profile hierarchy -
    1708             :     // all application preferences directories live alongside one another in
    1709             :     // ~/Library/Application Support/
    1710             :     rv = aFile->AppendNative(appName);
    1711             :   }
    1712             :   NS_ENSURE_SUCCESS(rv, rv);
    1713             : 
    1714             : #elif defined(XP_WIN)
    1715             :   if (!profile.IsEmpty()) {
    1716             :     rv = AppendProfileString(aFile, profile.get());
    1717             :   }
    1718             :   else {
    1719             :     if (!vendor.IsEmpty()) {
    1720             :       rv = aFile->AppendNative(vendor);
    1721             :       NS_ENSURE_SUCCESS(rv, rv);
    1722             :     }
    1723             :     rv = aFile->AppendNative(appName);
    1724             :   }
    1725             :   NS_ENSURE_SUCCESS(rv, rv);
    1726             : 
    1727             : #elif defined(ANDROID)
    1728             :   // The directory used for storing profiles
    1729             :   // The parent of this directory is set in GetUserDataDirectoryHome
    1730             :   // XXX: handle gAppData->profile properly
    1731             :   // XXXsmaug ...and the rest of the profile creation!
    1732             :   MOZ_ASSERT(!aAppName,
    1733             :              "Profile creation for external applications is not implemented!");
    1734             :   rv = aFile->AppendNative(nsDependentCString("mozilla"));
    1735             :   NS_ENSURE_SUCCESS(rv, rv);
    1736             : #elif defined(XP_UNIX)
    1737          10 :   nsAutoCString folder;
    1738             :   // Make it hidden (by starting with "."), except when local (the
    1739             :   // profile is already under ~/.cache or XDG_CACHE_HOME).
    1740           5 :   if (!aLocal)
    1741           4 :     folder.Assign('.');
    1742             : 
    1743           5 :   if (!profile.IsEmpty()) {
    1744             :     // Skip any leading path characters
    1745           0 :     const char* profileStart = profile.get();
    1746           0 :     while (*profileStart == '/' || *profileStart == '\\')
    1747           0 :       profileStart++;
    1748             : 
    1749             :     // On the off chance that someone wanted their folder to be hidden don't
    1750             :     // let it become ".."
    1751           0 :     if (*profileStart == '.' && !aLocal)
    1752           0 :       profileStart++;
    1753             : 
    1754           0 :     folder.Append(profileStart);
    1755           0 :     ToLowerCase(folder);
    1756             : 
    1757           0 :     rv = AppendProfileString(aFile, folder.BeginReading());
    1758             :   }
    1759             :   else {
    1760           5 :     if (!vendor.IsEmpty()) {
    1761           5 :       folder.Append(vendor);
    1762           5 :       ToLowerCase(folder);
    1763             : 
    1764           5 :       rv = aFile->AppendNative(folder);
    1765           5 :       NS_ENSURE_SUCCESS(rv, rv);
    1766             : 
    1767           5 :       folder.Truncate();
    1768             :     }
    1769             : 
    1770           5 :     folder.Append(appName);
    1771           5 :     ToLowerCase(folder);
    1772             : 
    1773           5 :     rv = aFile->AppendNative(folder);
    1774             :   }
    1775           5 :   NS_ENSURE_SUCCESS(rv, rv);
    1776             : 
    1777             : #else
    1778             : #error "Don't know how to get profile path on your platform"
    1779             : #endif
    1780           5 :   return NS_OK;
    1781             : }
    1782             : 
    1783             : nsresult
    1784           0 : nsXREDirProvider::AppendProfileString(nsIFile* aFile, const char* aPath)
    1785             : {
    1786           0 :   NS_ASSERTION(aFile, "Null file!");
    1787           0 :   NS_ASSERTION(aPath, "Null path!");
    1788             : 
    1789           0 :   nsAutoCString pathDup(aPath);
    1790             : 
    1791           0 :   char* path = pathDup.BeginWriting();
    1792             : 
    1793             :   nsresult rv;
    1794             :   char* subdir;
    1795           0 :   while ((subdir = NS_strtok("/\\", &path))) {
    1796           0 :     rv = aFile->AppendNative(nsDependentCString(subdir));
    1797           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1798             :   }
    1799             : 
    1800           0 :   return NS_OK;
    1801             : }

Generated by: LCOV version 1.13