toolkit/xre/nsXREDirProvider.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     6 #include "nsAppRunner.h"
     7 #include "nsToolkitCompsCID.h"
     8 #include "nsXREDirProvider.h"
    10 #include "jsapi.h"
    12 #include "nsIJSRuntimeService.h"
    13 #include "nsIAppStartup.h"
    14 #include "nsIDirectoryEnumerator.h"
    15 #include "nsIFile.h"
    16 #include "nsIObserver.h"
    17 #include "nsIObserverService.h"
    18 #include "nsISimpleEnumerator.h"
    19 #include "nsIToolkitChromeRegistry.h"
    21 #include "nsAppDirectoryServiceDefs.h"
    22 #include "nsDirectoryServiceDefs.h"
    23 #include "nsDirectoryServiceUtils.h"
    24 #include "nsXULAppAPI.h"
    25 #include "nsCategoryManagerUtils.h"
    27 #include "nsINIParser.h"
    28 #include "nsDependentString.h"
    29 #include "nsCOMArray.h"
    30 #include "nsArrayEnumerator.h"
    31 #include "nsEnumeratorUtils.h"
    32 #include "nsReadableUtils.h"
    33 #include "nsXPCOMPrivate.h"  // for XPCOM_FILE_PATH_SEPARATOR
    34 #include "mozilla/Services.h"
    35 #include "mozilla/Omnijar.h"
    36 #include "mozilla/Preferences.h"
    37 #include "mozilla/Telemetry.h"
    39 #include <stdlib.h>
    41 #ifdef XP_WIN
    42 #include <windows.h>
    43 #include <shlobj.h>
    44 #endif
    45 #ifdef XP_MACOSX
    46 #include "nsILocalFileMac.h"
    47 // for chflags()
    48 #include <sys/stat.h>
    49 #include <unistd.h>
    50 #endif
    51 #ifdef XP_UNIX
    52 #include <ctype.h>
    53 #endif
    55 #if defined(XP_MACOSX)
    56 #define APP_REGISTRY_NAME "Application Registry"
    57 #elif defined(XP_WIN)
    58 #define APP_REGISTRY_NAME "registry.dat"
    59 #else
    60 #define APP_REGISTRY_NAME "appreg"
    61 #endif
    63 #define PREF_OVERRIDE_DIRNAME "preferences"
    65 static already_AddRefed<nsIFile>
    66 CloneAndAppend(nsIFile* aFile, const char* name)
    67 {
    68   nsCOMPtr<nsIFile> file;
    69   aFile->Clone(getter_AddRefs(file));
    70   file->AppendNative(nsDependentCString(name));
    71   return file.forget();
    72 }
    74 nsXREDirProvider* gDirServiceProvider = nullptr;
    76 nsXREDirProvider::nsXREDirProvider() :
    77   mProfileNotified(false)
    78 {
    79   gDirServiceProvider = this;
    80 }
    82 nsXREDirProvider::~nsXREDirProvider()
    83 {
    84   gDirServiceProvider = nullptr;
    85 }
    87 nsXREDirProvider*
    88 nsXREDirProvider::GetSingleton()
    89 {
    90   return gDirServiceProvider;
    91 }
    93 nsresult
    94 nsXREDirProvider::Initialize(nsIFile *aXULAppDir,
    95                              nsIFile *aGREDir,
    96                              nsIDirectoryServiceProvider* aAppProvider)
    97 {
    98   NS_ENSURE_ARG(aXULAppDir);
    99   NS_ENSURE_ARG(aGREDir);
   101   mAppProvider = aAppProvider;
   102   mXULAppDir = aXULAppDir;
   103   mGREDir = aGREDir;
   105   if (!mProfileDir) {
   106     nsCOMPtr<nsIDirectoryServiceProvider> app(do_QueryInterface(mAppProvider));
   107     if (app) {
   108       bool per = false;
   109       app->GetFile(NS_APP_USER_PROFILE_50_DIR, &per, getter_AddRefs(mProfileDir));
   110       NS_ASSERTION(per, "NS_APP_USER_PROFILE_50_DIR must be persistent!"); 
   111       NS_ASSERTION(mProfileDir, "NS_APP_USER_PROFILE_50_DIR not defined! This shouldn't happen!"); 
   112     }
   113   }
   115   LoadAppBundleDirs();
   116   return NS_OK;
   117 }
   119 nsresult
   120 nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir)
   121 {
   122   NS_ASSERTION(aDir && aLocalDir, "We don't support no-profile apps yet!");
   124   nsresult rv;
   126   rv = EnsureDirectoryExists(aDir);
   127   if (NS_FAILED(rv))
   128     return rv;
   130   rv = EnsureDirectoryExists(aLocalDir);
   131   if (NS_FAILED(rv))
   132     return rv;
   134 #ifdef XP_MACOSX
   135   bool same;
   136   if (NS_SUCCEEDED(aDir->Equals(aLocalDir, &same)) && !same) {
   137     // Ensure that the cache directory is not indexed by Spotlight
   138     // (bug 718910).  At least on OS X, the cache directory (under
   139     // ~/Library/Caches/) is always the "local" user profile
   140     // directory.  This is confusing, since *both* user profile
   141     // directories are "local" (they both exist under the user's
   142     // home directory).  But this usage dates back at least as far
   143     // as the patch for bug 291033, where "local" seems to mean
   144     // "suitable for temporary storage".  Don't hide the cache
   145     // directory if by some chance it and the "non-local" profile
   146     // directory are the same -- there are bad side effects from
   147     // hiding a profile directory under /Library/Application Support/
   148     // (see bug 801883).
   149     nsAutoCString cacheDir;
   150     if (NS_SUCCEEDED(aLocalDir->GetNativePath(cacheDir))) {
   151       if (chflags(cacheDir.get(), UF_HIDDEN)) {
   152         NS_WARNING("Failed to set Cache directory to HIDDEN.");
   153       }
   154     }
   155   }
   156 #endif
   158   mProfileDir = aDir;
   159   mProfileLocalDir = aLocalDir;
   160   return NS_OK;
   161 }
   163 NS_IMPL_QUERY_INTERFACE(nsXREDirProvider,
   164                         nsIDirectoryServiceProvider,
   165                         nsIDirectoryServiceProvider2,
   166                         nsIProfileStartup)
   168 NS_IMETHODIMP_(MozExternalRefCountType)
   169 nsXREDirProvider::AddRef()
   170 {
   171   return 1;
   172 }
   174 NS_IMETHODIMP_(MozExternalRefCountType)
   175 nsXREDirProvider::Release()
   176 {
   177   return 0;
   178 }
   180 nsresult
   181 nsXREDirProvider::GetUserProfilesRootDir(nsIFile** aResult,
   182                                          const nsACString* aProfileName,
   183                                          const nsACString* aAppName,
   184                                          const nsACString* aVendorName)
   185 {
   186   nsCOMPtr<nsIFile> file;
   187   nsresult rv = GetUserDataDirectory(getter_AddRefs(file),
   188                                      false,
   189                                      aProfileName, aAppName, aVendorName);
   191   if (NS_SUCCEEDED(rv)) {
   192     // We must create the profile directory here if it does not exist.
   193     nsresult tmp = EnsureDirectoryExists(file);
   194     if (NS_FAILED(tmp)) {
   195       rv = tmp;
   196     }
   197   }
   198   file.swap(*aResult);
   199   return rv;
   200 }
   202 nsresult
   203 nsXREDirProvider::GetUserProfilesLocalDir(nsIFile** aResult,
   204                                           const nsACString* aProfileName,
   205                                           const nsACString* aAppName,
   206                                           const nsACString* aVendorName)
   207 {
   208   nsCOMPtr<nsIFile> file;
   209   nsresult rv = GetUserDataDirectory(getter_AddRefs(file),
   210                                      true,
   211                                      aProfileName, aAppName, aVendorName);
   213   if (NS_SUCCEEDED(rv)) {
   214     // We must create the profile directory here if it does not exist.
   215     nsresult tmp = EnsureDirectoryExists(file);
   216     if (NS_FAILED(tmp)) {
   217       rv = tmp;
   218     }
   219   }
   220   file.swap(*aResult);
   221   return NS_OK;
   222 }
   224 NS_IMETHODIMP
   225 nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
   226 			  nsIFile** aFile)
   227 {
   228   nsresult rv;
   230   bool gettingProfile = false;
   232   if (!strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR)) {
   233     // If XRE_NotifyProfile hasn't been called, don't fall through to
   234     // mAppProvider on the profile keys.
   235     if (!mProfileNotified)
   236       return NS_ERROR_FAILURE;
   238     if (mProfileLocalDir)
   239       return mProfileLocalDir->Clone(aFile);
   241     if (mAppProvider)
   242       return mAppProvider->GetFile(aProperty, aPersistent, aFile);
   244     // This falls through to the case below
   245     gettingProfile = true;
   246   }
   247   if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR) || gettingProfile) {
   248     if (!mProfileNotified)
   249       return NS_ERROR_FAILURE;
   251     if (mProfileDir)
   252       return mProfileDir->Clone(aFile);
   254     if (mAppProvider)
   255       return mAppProvider->GetFile(aProperty, aPersistent, aFile);
   257     // If we don't succeed here, bail early so that we aren't reentrant
   258     // through the "GetProfileDir" call below.
   259     return NS_ERROR_FAILURE;
   260   }
   262   if (mAppProvider) {
   263     rv = mAppProvider->GetFile(aProperty, aPersistent, aFile);
   264     if (NS_SUCCEEDED(rv) && *aFile)
   265       return rv;
   266   }
   268   *aPersistent = true;
   270   if (!strcmp(aProperty, NS_GRE_DIR)) {
   271     return mGREDir->Clone(aFile);
   272   }
   273   else if (!strcmp(aProperty, NS_OS_CURRENT_PROCESS_DIR) ||
   274       !strcmp(aProperty, NS_APP_INSTALL_CLEANUP_DIR)) {
   275     return GetAppDir()->Clone(aFile);
   276   }
   278   rv = NS_ERROR_FAILURE;
   279   nsCOMPtr<nsIFile> file;
   281   if (!strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_50_DIR) ||
   282            !strcmp(aProperty, NS_APP_PROFILE_DEFAULTS_NLOC_50_DIR)) {
   283     return GetProfileDefaultsDir(aFile);
   284   }
   285   else if (!strcmp(aProperty, NS_APP_PREF_DEFAULTS_50_DIR))
   286   {
   287     // return the GRE default prefs directory here, and the app default prefs
   288     // directory (if applicable) in NS_APP_PREFS_DEFAULTS_DIR_LIST.
   289     rv = mGREDir->Clone(getter_AddRefs(file));
   290     if (NS_SUCCEEDED(rv)) {
   291       rv = file->AppendNative(NS_LITERAL_CSTRING("defaults"));
   292       if (NS_SUCCEEDED(rv))
   293         rv = file->AppendNative(NS_LITERAL_CSTRING("pref"));
   294     }
   295   }
   296   else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_DIR) ||
   297            !strcmp(aProperty, XRE_USER_APP_DATA_DIR)) {
   298     rv = GetUserAppDataDirectory(getter_AddRefs(file));
   299   }
   300   else if (!strcmp(aProperty, XRE_UPDATE_ROOT_DIR)) {
   301     rv = GetUpdateRootDir(getter_AddRefs(file));
   302   }
   303   else if (!strcmp(aProperty, NS_APP_APPLICATION_REGISTRY_FILE)) {
   304     rv = GetUserAppDataDirectory(getter_AddRefs(file));
   305     if (NS_SUCCEEDED(rv))
   306       rv = file->AppendNative(NS_LITERAL_CSTRING(APP_REGISTRY_NAME));
   307   }
   308   else if (!strcmp(aProperty, NS_APP_USER_PROFILES_ROOT_DIR)) {
   309     rv = GetUserProfilesRootDir(getter_AddRefs(file), nullptr, nullptr, nullptr);
   310   }
   311   else if (!strcmp(aProperty, NS_APP_USER_PROFILES_LOCAL_ROOT_DIR)) {
   312     rv = GetUserProfilesLocalDir(getter_AddRefs(file), nullptr, nullptr, nullptr);
   313   }
   314   else if (!strcmp(aProperty, XRE_EXECUTABLE_FILE) && gArgv[0]) {
   315     nsCOMPtr<nsIFile> lf;
   316     rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(lf));
   317     if (NS_SUCCEEDED(rv))
   318       file = lf;
   319   }
   321   else if (!strcmp(aProperty, NS_APP_PROFILE_DIR_STARTUP) && mProfileDir) {
   322     return mProfileDir->Clone(aFile);
   323   }
   324   else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
   325     if (mProfileLocalDir)
   326       return mProfileLocalDir->Clone(aFile);
   328     if (mProfileDir)
   329       return mProfileDir->Clone(aFile);
   331     if (mAppProvider)
   332       return mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP, aPersistent,
   333                                    aFile);
   334   }
   335 #if defined(XP_UNIX) || defined(XP_MACOSX)
   336   else if (!strcmp(aProperty, XRE_SYS_LOCAL_EXTENSION_PARENT_DIR)) {
   337 #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
   338     return GetSystemExtensionsDirectory(aFile);
   339 #else
   340     return NS_ERROR_FAILURE;
   341 #endif
   342   }
   343 #endif
   344 #if defined(XP_UNIX) && !defined(XP_MACOSX)
   345   else if (!strcmp(aProperty, XRE_SYS_SHARE_EXTENSION_PARENT_DIR)) {
   346 #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
   347 #if defined(__OpenBSD__) || defined(__FreeBSD__)
   348     static const char *const sysLExtDir = "/usr/local/share/mozilla/extensions";
   349 #else
   350     static const char *const sysLExtDir = "/usr/share/mozilla/extensions";
   351 #endif
   352     return NS_NewNativeLocalFile(nsDependentCString(sysLExtDir),
   353                                  false, aFile);
   354 #else
   355     return NS_ERROR_FAILURE;
   356 #endif
   357   }
   358 #endif
   359   else if (!strcmp(aProperty, XRE_USER_SYS_EXTENSION_DIR)) {
   360 #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
   361     return GetSysUserExtensionsDirectory(aFile);
   362 #else
   363     return NS_ERROR_FAILURE;
   364 #endif
   365   }
   366   else if (!strcmp(aProperty, XRE_APP_DISTRIBUTION_DIR)) {
   367     bool persistent = false;
   368     rv = GetFile(XRE_EXECUTABLE_FILE, &persistent, getter_AddRefs(file));
   369     if (NS_SUCCEEDED(rv))
   370       rv = file->SetNativeLeafName(NS_LITERAL_CSTRING("distribution"));
   371   }
   372   else if (NS_SUCCEEDED(GetProfileStartupDir(getter_AddRefs(file)))) {
   373     // We need to allow component, xpt, and chrome registration to
   374     // occur prior to the profile-after-change notification.
   375     if (!strcmp(aProperty, NS_APP_USER_CHROME_DIR)) {
   376       rv = file->AppendNative(NS_LITERAL_CSTRING("chrome"));
   377     }
   378   }
   380   if (NS_SUCCEEDED(rv) && file) {
   381     NS_ADDREF(*aFile = file);
   382     return NS_OK;
   383   }
   385   bool ensureFilePermissions = false;
   387   if (NS_SUCCEEDED(GetProfileDir(getter_AddRefs(file)))) {
   388     if (!strcmp(aProperty, NS_APP_PREFS_50_DIR)) {
   389       rv = NS_OK;
   390     }
   391     else if (!strcmp(aProperty, NS_APP_PREFS_50_FILE)) {
   392       rv = file->AppendNative(NS_LITERAL_CSTRING("prefs.js"));
   393     }
   394     else if (!strcmp(aProperty, NS_METRO_APP_PREFS_50_FILE)) {
   395       rv = file->AppendNative(NS_LITERAL_CSTRING("metro-prefs.js"));
   396     }
   397     else if (!strcmp(aProperty, NS_LOCALSTORE_UNSAFE_FILE)) {
   398       rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
   399     }
   400     else if (!strcmp(aProperty, NS_APP_LOCALSTORE_50_FILE)) {
   401       if (gSafeMode) {
   402         rv = file->AppendNative(NS_LITERAL_CSTRING("localstore-safe.rdf"));
   403         file->Remove(false);
   404       }
   405       else {
   406         rv = file->AppendNative(NS_LITERAL_CSTRING("localstore.rdf"));
   407         EnsureProfileFileExists(file);
   408         ensureFilePermissions = true;
   409       }
   410     }
   411     else if (!strcmp(aProperty, NS_APP_USER_MIMETYPES_50_FILE)) {
   412       rv = file->AppendNative(NS_LITERAL_CSTRING("mimeTypes.rdf"));
   413       EnsureProfileFileExists(file);
   414       ensureFilePermissions = true;
   415     }
   416     else if (!strcmp(aProperty, NS_APP_DOWNLOADS_50_FILE)) {
   417       rv = file->AppendNative(NS_LITERAL_CSTRING("downloads.rdf"));
   418     }
   419     else if (!strcmp(aProperty, NS_APP_PREFS_OVERRIDE_DIR)) {
   420       rv = mProfileDir->Clone(getter_AddRefs(file));
   421       nsresult tmp = file->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));
   422       if (NS_FAILED(tmp)) {
   423         rv = tmp;
   424       }
   425       tmp = EnsureDirectoryExists(file);
   426       if (NS_FAILED(tmp)) {
   427         rv = tmp;
   428       }
   429     }
   430   }
   431   if (NS_FAILED(rv) || !file)
   432     return NS_ERROR_FAILURE;
   434   if (ensureFilePermissions) {
   435     bool fileToEnsureExists;
   436     bool isWritable;
   437     if (NS_SUCCEEDED(file->Exists(&fileToEnsureExists)) && fileToEnsureExists
   438         && NS_SUCCEEDED(file->IsWritable(&isWritable)) && !isWritable) {
   439       uint32_t permissions;
   440       if (NS_SUCCEEDED(file->GetPermissions(&permissions))) {
   441         rv = file->SetPermissions(permissions | 0600);
   442         NS_ASSERTION(NS_SUCCEEDED(rv), "failed to ensure file permissions");
   443       }
   444     }
   445   }
   447   NS_ADDREF(*aFile = file);
   448   return NS_OK;
   449 }
   451 static void
   452 LoadDirIntoArray(nsIFile* dir,
   453                  const char *const *aAppendList,
   454                  nsCOMArray<nsIFile>& aDirectories)
   455 {
   456   if (!dir)
   457     return;
   459   nsCOMPtr<nsIFile> subdir;
   460   dir->Clone(getter_AddRefs(subdir));
   461   if (!subdir)
   462     return;
   464   for (const char *const *a = aAppendList; *a; ++a) {
   465     subdir->AppendNative(nsDependentCString(*a));
   466   }
   468   bool exists;
   469   if (NS_SUCCEEDED(subdir->Exists(&exists)) && exists) {
   470     aDirectories.AppendObject(subdir);
   471   }
   472 }
   474 static void
   475 LoadDirsIntoArray(nsCOMArray<nsIFile>& aSourceDirs,
   476                   const char *const* aAppendList,
   477                   nsCOMArray<nsIFile>& aDirectories)
   478 {
   479   nsCOMPtr<nsIFile> appended;
   480   bool exists;
   482   for (int32_t i = 0; i < aSourceDirs.Count(); ++i) {
   483     aSourceDirs[i]->Clone(getter_AddRefs(appended));
   484     if (!appended)
   485       continue;
   487     nsAutoCString leaf;
   488     appended->GetNativeLeafName(leaf);
   489     if (!Substring(leaf, leaf.Length() - 4).Equals(NS_LITERAL_CSTRING(".xpi"))) {
   490       LoadDirIntoArray(appended,
   491                        aAppendList,
   492                        aDirectories);
   493     }
   494     else if (NS_SUCCEEDED(appended->Exists(&exists)) && exists)
   495       aDirectories.AppendObject(appended);
   496   }
   497 }
   499 NS_IMETHODIMP
   500 nsXREDirProvider::GetFiles(const char* aProperty, nsISimpleEnumerator** aResult)
   501 {
   502   nsresult rv;
   504   nsCOMPtr<nsISimpleEnumerator> appEnum;
   505   nsCOMPtr<nsIDirectoryServiceProvider2>
   506     appP2(do_QueryInterface(mAppProvider));
   507   if (appP2) {
   508     rv = appP2->GetFiles(aProperty, getter_AddRefs(appEnum));
   509     if (NS_FAILED(rv)) {
   510       appEnum = nullptr;
   511     }
   512     else if (rv != NS_SUCCESS_AGGREGATE_RESULT) {
   513       NS_ADDREF(*aResult = appEnum);
   514       return NS_OK;
   515     }
   516   }
   518   nsCOMPtr<nsISimpleEnumerator> xreEnum;
   519   rv = GetFilesInternal(aProperty, getter_AddRefs(xreEnum));
   520   if (NS_FAILED(rv)) {
   521     if (appEnum) {
   522       NS_ADDREF(*aResult = appEnum);
   523       return NS_SUCCESS_AGGREGATE_RESULT;
   524     }
   526     return rv;
   527   }
   529   rv = NS_NewUnionEnumerator(aResult, appEnum, xreEnum);
   530   if (NS_FAILED(rv))
   531     return rv;
   533   return NS_SUCCESS_AGGREGATE_RESULT;
   534 }
   536 static void
   537 LoadExtensionDirectories(nsINIParser &parser,
   538                          const char *aSection,
   539                          nsCOMArray<nsIFile> &aDirectories,
   540                          NSLocationType aType)
   541 {
   542   nsresult rv;
   543   int32_t i = 0;
   544   do {
   545     nsAutoCString buf("Extension");
   546     buf.AppendInt(i++);
   548     nsAutoCString path;
   549     rv = parser.GetString(aSection, buf.get(), path);
   550     if (NS_FAILED(rv))
   551       return;
   553     nsCOMPtr<nsIFile> dir = do_CreateInstance("@mozilla.org/file/local;1", &rv);
   554     if (NS_FAILED(rv))
   555       continue;
   557     rv = dir->SetPersistentDescriptor(path);
   558     if (NS_FAILED(rv))
   559       continue;
   561     aDirectories.AppendObject(dir);
   562     if (Substring(path, path.Length() - 4).Equals(NS_LITERAL_CSTRING(".xpi"))) {
   563       XRE_AddJarManifestLocation(aType, dir);
   564     }
   565     else {
   566       nsCOMPtr<nsIFile> manifest =
   567         CloneAndAppend(dir, "chrome.manifest");
   568       XRE_AddManifestLocation(aType, manifest);
   569     }
   570   }
   571   while (true);
   572 }
   574 void
   575 nsXREDirProvider::LoadExtensionBundleDirectories()
   576 {
   577   if (!mozilla::Preferences::GetBool("extensions.defaultProviders.enabled", true))
   578     return;
   580   if (mProfileDir && !gSafeMode) {
   581     nsCOMPtr<nsIFile> extensionsINI;
   582     mProfileDir->Clone(getter_AddRefs(extensionsINI));
   583     if (!extensionsINI)
   584       return;
   586     extensionsINI->AppendNative(NS_LITERAL_CSTRING("extensions.ini"));
   588     nsCOMPtr<nsIFile> extensionsINILF =
   589       do_QueryInterface(extensionsINI);
   590     if (!extensionsINILF)
   591       return;
   593     nsINIParser parser;
   594     nsresult rv = parser.Init(extensionsINILF);
   595     if (NS_FAILED(rv))
   596       return;
   598     LoadExtensionDirectories(parser, "ExtensionDirs", mExtensionDirectories,
   599                              NS_COMPONENT_LOCATION);
   600     LoadExtensionDirectories(parser, "ThemeDirs", mThemeDirectories,
   601                              NS_SKIN_LOCATION);
   602   }
   603 }
   605 void
   606 nsXREDirProvider::LoadAppBundleDirs()
   607 {
   608   nsCOMPtr<nsIFile> dir;
   609   bool persistent = false;
   610   nsresult rv = GetFile(XRE_EXECUTABLE_FILE, &persistent, getter_AddRefs(dir));
   611   if (NS_FAILED(rv))
   612     return;
   614   dir->SetNativeLeafName(NS_LITERAL_CSTRING("distribution"));
   615   dir->AppendNative(NS_LITERAL_CSTRING("bundles"));
   617   nsCOMPtr<nsISimpleEnumerator> e;
   618   rv = dir->GetDirectoryEntries(getter_AddRefs(e));
   619   if (NS_FAILED(rv))
   620     return;
   622   nsCOMPtr<nsIDirectoryEnumerator> files = do_QueryInterface(e);
   623   if (!files)
   624     return;
   626   nsCOMPtr<nsIFile> subdir;
   627   while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(subdir))) && subdir) {
   628     mAppBundleDirectories.AppendObject(subdir);
   630     nsCOMPtr<nsIFile> manifest =
   631       CloneAndAppend(subdir, "chrome.manifest");
   632     XRE_AddManifestLocation(NS_COMPONENT_LOCATION, manifest);
   633   }
   634 }
   636 static const char *const kAppendPrefDir[] = { "defaults", "preferences", nullptr };
   638 #ifdef DEBUG_bsmedberg
   639 static void
   640 DumpFileArray(const char *key,
   641               nsCOMArray<nsIFile> dirs)
   642 {
   643   fprintf(stderr, "nsXREDirProvider::GetFilesInternal(%s)\n", key);
   645   nsAutoCString path;
   646   for (int32_t i = 0; i < dirs.Count(); ++i) {
   647     dirs[i]->GetNativePath(path);
   648     fprintf(stderr, "  %s\n", path.get());
   649   }
   650 }
   651 #endif // DEBUG_bsmedberg
   653 nsresult
   654 nsXREDirProvider::GetFilesInternal(const char* aProperty,
   655                                    nsISimpleEnumerator** aResult)
   656 {
   657   nsresult rv = NS_OK;
   658   *aResult = nullptr;
   660   if (!strcmp(aProperty, XRE_EXTENSIONS_DIR_LIST)) {
   661     nsCOMArray<nsIFile> directories;
   663     static const char *const kAppendNothing[] = { nullptr };
   665     LoadDirsIntoArray(mAppBundleDirectories,
   666                       kAppendNothing, directories);
   667     LoadDirsIntoArray(mExtensionDirectories,
   668                       kAppendNothing, directories);
   670     rv = NS_NewArrayEnumerator(aResult, directories);
   671   }
   672   else if (!strcmp(aProperty, NS_APP_PREFS_DEFAULTS_DIR_LIST)) {
   673     nsCOMArray<nsIFile> directories;
   675     LoadDirIntoArray(mXULAppDir, kAppendPrefDir, directories);
   676     LoadDirsIntoArray(mAppBundleDirectories,
   677                       kAppendPrefDir, directories);
   679     rv = NS_NewArrayEnumerator(aResult, directories);
   680   }
   681   else if (!strcmp(aProperty, NS_EXT_PREFS_DEFAULTS_DIR_LIST)) {
   682     nsCOMArray<nsIFile> directories;
   684     LoadDirsIntoArray(mExtensionDirectories,
   685                       kAppendPrefDir, directories);
   687     if (mProfileDir) {
   688       nsCOMPtr<nsIFile> overrideFile;
   689       mProfileDir->Clone(getter_AddRefs(overrideFile));
   690       overrideFile->AppendNative(NS_LITERAL_CSTRING(PREF_OVERRIDE_DIRNAME));
   692       bool exists;
   693       if (NS_SUCCEEDED(overrideFile->Exists(&exists)) && exists)
   694         directories.AppendObject(overrideFile);
   695     }
   697     rv = NS_NewArrayEnumerator(aResult, directories);
   698   }
   699   else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) {
   700     // NS_APP_CHROME_DIR_LIST is only used to get default (native) icons
   701     // for OS window decoration.
   703     static const char *const kAppendChromeDir[] = { "chrome", nullptr };
   704     nsCOMArray<nsIFile> directories;
   705     LoadDirIntoArray(mXULAppDir,
   706                      kAppendChromeDir,
   707                      directories);
   708     LoadDirsIntoArray(mAppBundleDirectories,
   709                       kAppendChromeDir,
   710                       directories);
   711     LoadDirsIntoArray(mExtensionDirectories,
   712                       kAppendChromeDir,
   713                       directories);
   715     rv = NS_NewArrayEnumerator(aResult, directories);
   716   }
   717   else if (!strcmp(aProperty, NS_APP_PLUGINS_DIR_LIST)) {
   718     nsCOMArray<nsIFile> directories;
   720     if (mozilla::Preferences::GetBool("plugins.load_appdir_plugins", false)) {
   721       nsCOMPtr<nsIFile> appdir;
   722       rv = XRE_GetBinaryPath(gArgv[0], getter_AddRefs(appdir));
   723       if (NS_SUCCEEDED(rv)) {
   724         appdir->SetNativeLeafName(NS_LITERAL_CSTRING("plugins"));
   725         directories.AppendObject(appdir);
   726       }
   727     }
   729     static const char *const kAppendPlugins[] = { "plugins", nullptr };
   731     // The root dirserviceprovider does quite a bit for us: we're mainly
   732     // interested in xulapp and extension-provided plugins.
   733     LoadDirsIntoArray(mAppBundleDirectories,
   734                       kAppendPlugins,
   735                       directories);
   736     LoadDirsIntoArray(mExtensionDirectories,
   737                       kAppendPlugins,
   738                       directories);
   740     if (mProfileDir) {
   741       nsCOMArray<nsIFile> profileDir;
   742       profileDir.AppendObject(mProfileDir);
   743       LoadDirsIntoArray(profileDir,
   744                         kAppendPlugins,
   745                         directories);
   746     }
   748     rv = NS_NewArrayEnumerator(aResult, directories);
   749     NS_ENSURE_SUCCESS(rv, rv);
   751     rv = NS_SUCCESS_AGGREGATE_RESULT;
   752   }
   753   else
   754     rv = NS_ERROR_FAILURE;
   756   return rv;
   757 }
   759 NS_IMETHODIMP
   760 nsXREDirProvider::GetDirectory(nsIFile* *aResult)
   761 {
   762   NS_ENSURE_TRUE(mProfileDir, NS_ERROR_NOT_INITIALIZED);
   764   return mProfileDir->Clone(aResult);
   765 }
   767 NS_IMETHODIMP
   768 nsXREDirProvider::DoStartup()
   769 {
   770   if (!mProfileNotified) {
   771     nsCOMPtr<nsIObserverService> obsSvc =
   772       mozilla::services::GetObserverService();
   773     if (!obsSvc) return NS_ERROR_FAILURE;
   775     mProfileNotified = true;
   777     /*
   778        Setup prefs before profile-do-change to be able to use them to track
   779        crashes and because we want to begin crash tracking before other code run
   780        from this notification since they may cause crashes.
   781     */
   782     nsresult rv = mozilla::Preferences::ResetAndReadUserPrefs();
   783     if (NS_FAILED(rv)) NS_WARNING("Failed to setup pref service.");
   785     bool safeModeNecessary = false;
   786     nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
   787     if (appStartup) {
   788       rv = appStartup->TrackStartupCrashBegin(&safeModeNecessary);
   789       if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE)
   790         NS_WARNING("Error while beginning startup crash tracking");
   792       if (!gSafeMode && safeModeNecessary) {
   793         appStartup->RestartInSafeMode(nsIAppStartup::eForceQuit);
   794         return NS_OK;
   795       }
   796     }
   798     static const char16_t kStartup[] = {'s','t','a','r','t','u','p','\0'};
   799     obsSvc->NotifyObservers(nullptr, "profile-do-change", kStartup);
   800     // Init the Extension Manager
   801     nsCOMPtr<nsIObserver> em = do_GetService("@mozilla.org/addons/integration;1");
   802     if (em) {
   803       em->Observe(nullptr, "addons-startup", nullptr);
   804     } else {
   805       NS_WARNING("Failed to create Addons Manager.");
   806     }
   808     LoadExtensionBundleDirectories();
   810     obsSvc->NotifyObservers(nullptr, "load-extension-defaults", nullptr);
   811     obsSvc->NotifyObservers(nullptr, "profile-after-change", kStartup);
   813     // Any component that has registered for the profile-after-change category
   814     // should also be created at this time.
   815     (void)NS_CreateServicesFromCategory("profile-after-change", nullptr,
   816                                         "profile-after-change");
   818     if (gSafeMode && safeModeNecessary) {
   819       static const char16_t kCrashed[] = {'c','r','a','s','h','e','d','\0'};
   820       obsSvc->NotifyObservers(nullptr, "safemode-forced", kCrashed);
   821     }
   823     // 1 = Regular mode, 2 = Safe mode, 3 = Safe mode forced
   824     int mode = 1;
   825     if (gSafeMode) {
   826       if (safeModeNecessary)
   827         mode = 3;
   828       else
   829         mode = 2;
   830     }
   831     mozilla::Telemetry::Accumulate(mozilla::Telemetry::SAFE_MODE_USAGE, mode);
   833     obsSvc->NotifyObservers(nullptr, "profile-initial-state", nullptr);
   834   }
   835   return NS_OK;
   836 }
   838 void
   839 nsXREDirProvider::DoShutdown()
   840 {
   841   if (mProfileNotified) {
   842     nsCOMPtr<nsIObserverService> obsSvc =
   843       mozilla::services::GetObserverService();
   844     NS_ASSERTION(obsSvc, "No observer service?");
   845     if (obsSvc) {
   846       static const char16_t kShutdownPersist[] =
   847         {'s','h','u','t','d','o','w','n','-','p','e','r','s','i','s','t','\0'};
   848       obsSvc->NotifyObservers(nullptr, "profile-change-net-teardown", kShutdownPersist);
   849       obsSvc->NotifyObservers(nullptr, "profile-change-teardown", kShutdownPersist);
   851       // Phase 2c: Now that things are torn down, force JS GC so that things which depend on
   852       // resources which are about to go away in "profile-before-change" are destroyed first.
   854       nsCOMPtr<nsIJSRuntimeService> rtsvc
   855         (do_GetService("@mozilla.org/js/xpc/RuntimeService;1"));
   856       if (rtsvc)
   857       {
   858         JSRuntime *rt = nullptr;
   859         rtsvc->GetRuntime(&rt);
   860         if (rt)
   861           ::JS_GC(rt);
   862       }
   864       // Phase 3: Notify observers of a profile change
   865       obsSvc->NotifyObservers(nullptr, "profile-before-change", kShutdownPersist);
   866       obsSvc->NotifyObservers(nullptr, "profile-before-change2", kShutdownPersist);
   867     }
   868     mProfileNotified = false;
   869   }
   870 }
   872 #ifdef XP_WIN
   873 static nsresult
   874 GetShellFolderPath(int folder, nsAString& _retval)
   875 {
   876   wchar_t* buf;
   877   uint32_t bufLength = _retval.GetMutableData(&buf, MAXPATHLEN + 3);
   878   NS_ENSURE_TRUE(bufLength >= (MAXPATHLEN + 3), NS_ERROR_OUT_OF_MEMORY);
   880   nsresult rv = NS_OK;
   882   LPITEMIDLIST pItemIDList = nullptr;
   884   if (SUCCEEDED(SHGetSpecialFolderLocation(nullptr, folder, &pItemIDList)) &&
   885       SHGetPathFromIDListW(pItemIDList, buf)) {
   886     // We're going to use wcslen (wcsnlen not available in msvc7.1) so make
   887     // sure to null terminate.
   888     buf[bufLength - 1] = L'\0';
   889     _retval.SetLength(wcslen(buf));
   890   } else {
   891     _retval.SetLength(0);
   892     rv = NS_ERROR_NOT_AVAILABLE;
   893   }
   895   CoTaskMemFree(pItemIDList);
   897   return rv;
   898 }
   900 /**
   901  * Provides a fallback for getting the path to APPDATA or LOCALAPPDATA by
   902  * querying the registry when the call to SHGetSpecialFolderLocation or
   903  * SHGetPathFromIDListW is unable to provide these paths (Bug 513958).
   904  */
   905 static nsresult
   906 GetRegWindowsAppDataFolder(bool aLocal, nsAString& _retval)
   907 {
   908   HKEY key;
   909   NS_NAMED_LITERAL_STRING(keyName,
   910   "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders");
   911   DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, keyName.get(), 0, KEY_READ,
   912                               &key);
   913   if (res != ERROR_SUCCESS) {
   914     _retval.SetLength(0);
   915     return NS_ERROR_NOT_AVAILABLE;
   916   }
   918   DWORD type, size;
   919   res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
   920                          nullptr, &type, nullptr, &size);
   921   // The call to RegQueryValueExW must succeed, the type must be REG_SZ, the
   922   // buffer size must not equal 0, and the buffer size be a multiple of 2.
   923   if (res != ERROR_SUCCESS || type != REG_SZ || size == 0 || size % 2 != 0) {
   924     ::RegCloseKey(key);
   925     _retval.SetLength(0);
   926     return NS_ERROR_NOT_AVAILABLE;
   927   }
   929   // |size| may or may not include room for the terminating null character
   930   DWORD resultLen = size / 2;
   932   _retval.SetLength(resultLen);
   933   nsAString::iterator begin;
   934   _retval.BeginWriting(begin);
   935   if (begin.size_forward() != resultLen) {
   936     ::RegCloseKey(key);
   937     _retval.SetLength(0);
   938     return NS_ERROR_NOT_AVAILABLE;
   939   }
   941   res = RegQueryValueExW(key, (aLocal ? L"Local AppData" : L"AppData"),
   942                          nullptr, nullptr, (LPBYTE) begin.get(), &size);
   943   ::RegCloseKey(key);
   944   if (res != ERROR_SUCCESS) {
   945     _retval.SetLength(0);
   946     return NS_ERROR_NOT_AVAILABLE;
   947   }
   949   if (!_retval.CharAt(resultLen - 1)) {
   950     // It was already null terminated.
   951     _retval.Truncate(resultLen - 1);
   952   }
   954   return NS_OK;
   955 }
   957 static bool
   958 GetCachedHash(HKEY rootKey, const nsAString &regPath, const nsAString &path,
   959               nsAString &cachedHash)
   960 {
   961   HKEY baseKey;
   962   if (RegOpenKeyExW(rootKey, reinterpret_cast<const wchar_t*>(regPath.BeginReading()), 0, KEY_READ, &baseKey) !=
   963       ERROR_SUCCESS) {
   964     return false;
   965   }
   967   wchar_t cachedHashRaw[512];
   968   DWORD bufferSize = sizeof(cachedHashRaw);
   969   LONG result = RegQueryValueExW(baseKey, reinterpret_cast<const wchar_t*>(path.BeginReading()), 0, nullptr,
   970                                  (LPBYTE)cachedHashRaw, &bufferSize);
   971   RegCloseKey(baseKey);
   972   if (result == ERROR_SUCCESS) {
   973     cachedHash.Assign(cachedHashRaw);
   974   }
   975   return ERROR_SUCCESS == result;
   976 }
   978 #endif
   980 nsresult
   981 nsXREDirProvider::GetUpdateRootDir(nsIFile* *aResult)
   982 {
   983   nsCOMPtr<nsIFile> updRoot;
   984 #if defined(MOZ_WIDGET_GONK)
   986   nsresult rv = NS_NewNativeLocalFile(nsDependentCString("/data/local"),
   987                                       true,
   988                                       getter_AddRefs(updRoot));
   989   NS_ENSURE_SUCCESS(rv, rv);
   991 #else
   992   nsCOMPtr<nsIFile> appFile;
   993   bool per = false;
   994   nsresult rv = GetFile(XRE_EXECUTABLE_FILE, &per, getter_AddRefs(appFile));
   995   NS_ENSURE_SUCCESS(rv, rv);
   996   rv = appFile->GetParent(getter_AddRefs(updRoot));
   997   NS_ENSURE_SUCCESS(rv, rv);
   999 #ifdef XP_WIN
  1001   nsAutoString pathHash;
  1002   bool pathHashResult = false;
  1003   bool hasVendor = gAppData->vendor && strlen(gAppData->vendor) != 0;
  1005   nsAutoString appDirPath;
  1006   if (SUCCEEDED(updRoot->GetPath(appDirPath))) {
  1008     // Figure out where we should check for a cached hash value. If the
  1009     // application doesn't have the nsXREAppData vendor value defined check
  1010     // under SOFTWARE\Mozilla.
  1011     wchar_t regPath[1024] = { L'\0' };
  1012     swprintf_s(regPath, mozilla::ArrayLength(regPath), L"SOFTWARE\\%S\\%S\\TaskBarIDs",
  1013                (hasVendor ? gAppData->vendor : "Mozilla"), MOZ_APP_BASENAME);
  1015     // If we pre-computed the hash, grab it from the registry.
  1016     pathHashResult = GetCachedHash(HKEY_LOCAL_MACHINE,
  1017                                    nsDependentString(regPath), appDirPath,
  1018                                    pathHash);
  1019     if (!pathHashResult) {
  1020       pathHashResult = GetCachedHash(HKEY_CURRENT_USER,
  1021                                      nsDependentString(regPath), appDirPath,
  1022                                      pathHash);
  1026   // Get the local app data directory and if a vendor name exists append it.
  1027   // If only a product name exists, append it.  If neither exist fallback to
  1028   // old handling.  We don't use the product name on purpose because we want a
  1029   // shared update directory for different apps run from the same path (like
  1030   // Metro & Desktop).
  1031   nsCOMPtr<nsIFile> localDir;
  1032   if (pathHashResult && (hasVendor || gAppData->name) &&
  1033       NS_SUCCEEDED(GetUserDataDirectoryHome(getter_AddRefs(localDir), true)) &&
  1034       NS_SUCCEEDED(localDir->AppendNative(nsDependentCString(hasVendor ?
  1035                                           gAppData->vendor : gAppData->name))) &&
  1036       NS_SUCCEEDED(localDir->Append(NS_LITERAL_STRING("updates"))) &&
  1037       NS_SUCCEEDED(localDir->Append(pathHash))) {
  1038     NS_ADDREF(*aResult = localDir);
  1039     return NS_OK;
  1042   nsAutoString appPath;
  1043   rv = updRoot->GetPath(appPath);
  1044   NS_ENSURE_SUCCESS(rv, rv);
  1046   // AppDir may be a short path. Convert to long path to make sure
  1047   // the consistency of the update folder location
  1048   nsString longPath;
  1049   wchar_t* buf;
  1051   uint32_t bufLength = longPath.GetMutableData(&buf, MAXPATHLEN);
  1052   NS_ENSURE_TRUE(bufLength >= MAXPATHLEN, NS_ERROR_OUT_OF_MEMORY);
  1054   DWORD len = GetLongPathNameW(appPath.get(), buf, bufLength);
  1056   // Failing GetLongPathName() is not fatal.
  1057   if (len <= 0 || len >= bufLength)
  1058     longPath.Assign(appPath);
  1059   else
  1060     longPath.SetLength(len);
  1062   // Use <UserLocalDataDir>\updates\<relative path to app dir from
  1063   // Program Files> if app dir is under Program Files to avoid the
  1064   // folder virtualization mess on Windows Vista
  1065   nsAutoString programFiles;
  1066   rv = GetShellFolderPath(CSIDL_PROGRAM_FILES, programFiles);
  1067   NS_ENSURE_SUCCESS(rv, rv);
  1069   programFiles.AppendLiteral("\\");
  1070   uint32_t programFilesLen = programFiles.Length();
  1072   nsAutoString programName;
  1073   if (_wcsnicmp(programFiles.get(), longPath.get(), programFilesLen) == 0) {
  1074     programName = Substring(longPath, programFilesLen);
  1075   } else {
  1076     // We need the update root directory to live outside of the installation
  1077     // directory, because otherwise the updater writing the log file can cause
  1078     // the directory to be locked, which prevents it from being replaced after
  1079     // background updates.
  1080     programName.AssignASCII(MOZ_APP_NAME);
  1083   rv = GetUserLocalDataDirectory(getter_AddRefs(updRoot));
  1084   NS_ENSURE_SUCCESS(rv, rv);
  1086   rv = updRoot->AppendRelativePath(programName);
  1087   NS_ENSURE_SUCCESS(rv, rv);
  1089 #endif
  1090 #endif
  1091   NS_ADDREF(*aResult = updRoot);
  1092   return NS_OK;
  1095 nsresult
  1096 nsXREDirProvider::GetProfileStartupDir(nsIFile* *aResult)
  1098   if (mProfileDir)
  1099     return mProfileDir->Clone(aResult);
  1101   if (mAppProvider) {
  1102     nsCOMPtr<nsIFile> needsclone;
  1103     bool dummy;
  1104     nsresult rv = mAppProvider->GetFile(NS_APP_PROFILE_DIR_STARTUP,
  1105                                         &dummy,
  1106                                         getter_AddRefs(needsclone));
  1107     if (NS_SUCCEEDED(rv))
  1108       return needsclone->Clone(aResult);
  1111   return NS_ERROR_FAILURE;
  1114 nsresult
  1115 nsXREDirProvider::GetProfileDir(nsIFile* *aResult)
  1117   if (mProfileDir) {
  1118     if (!mProfileNotified)
  1119       return NS_ERROR_FAILURE;
  1121     return mProfileDir->Clone(aResult);
  1124   if (mAppProvider) {
  1125     nsCOMPtr<nsIFile> needsclone;
  1126     bool dummy;
  1127     nsresult rv = mAppProvider->GetFile(NS_APP_USER_PROFILE_50_DIR,
  1128                                         &dummy,
  1129                                         getter_AddRefs(needsclone));
  1130     if (NS_SUCCEEDED(rv))
  1131       return needsclone->Clone(aResult);
  1134   return NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, aResult);
  1137 nsresult
  1138 nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal)
  1140   // Copied from nsAppFileLocationProvider (more or less)
  1141   NS_ENSURE_ARG_POINTER(aFile);
  1142   nsCOMPtr<nsIFile> localDir;
  1144   nsresult rv = GetAppDir()->Clone(getter_AddRefs(localDir));
  1145   NS_ENSURE_SUCCESS(rv, rv);
  1147   int levelsToRemove = 1; // In FF21+, appDir points to browser subdirectory.
  1148 #if defined(XP_MACOSX)
  1149   levelsToRemove += 2;
  1150 #endif
  1151   while (localDir && (levelsToRemove > 0)) {
  1152     // When crawling up the hierarchy, components named "." do not count.
  1153     nsAutoCString removedName;
  1154     rv = localDir->GetNativeLeafName(removedName);
  1155     NS_ENSURE_SUCCESS(rv, rv);
  1156     bool didRemove = !removedName.Equals(".");
  1158     // Remove a directory component.
  1159     nsCOMPtr<nsIFile> parentDir;
  1160     rv = localDir->GetParent(getter_AddRefs(parentDir));
  1161     NS_ENSURE_SUCCESS(rv, rv);
  1162     localDir = parentDir;
  1164     if (didRemove)
  1165       --levelsToRemove;
  1168   if (!localDir)
  1169     return NS_ERROR_FAILURE;
  1171   rv = localDir->AppendRelativeNativePath(NS_LITERAL_CSTRING("TorBrowser"
  1172                                      XPCOM_FILE_PATH_SEPARATOR "Data"
  1173                                      XPCOM_FILE_PATH_SEPARATOR "Browser"));
  1174   NS_ENSURE_SUCCESS(rv, rv);
  1176   if (aLocal) {
  1177     rv = localDir->AppendNative(NS_LITERAL_CSTRING("Caches"));
  1178     NS_ENSURE_SUCCESS(rv, rv);
  1181   NS_IF_ADDREF(*aFile = localDir);
  1182   return rv;
  1185 nsresult
  1186 nsXREDirProvider::GetSysUserExtensionsDirectory(nsIFile** aFile)
  1188   nsCOMPtr<nsIFile> localDir;
  1189   nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), false);
  1190   NS_ENSURE_SUCCESS(rv, rv);
  1192   rv = AppendSysUserExtensionPath(localDir);
  1193   NS_ENSURE_SUCCESS(rv, rv);
  1195   rv = EnsureDirectoryExists(localDir);
  1196   NS_ENSURE_SUCCESS(rv, rv);
  1198   NS_ADDREF(*aFile = localDir);
  1199   return NS_OK;
  1202 #if defined(XP_UNIX) || defined(XP_MACOSX)
  1203 nsresult
  1204 nsXREDirProvider::GetSystemExtensionsDirectory(nsIFile** aFile)
  1206   nsresult rv;
  1207   nsCOMPtr<nsIFile> localDir;
  1208 #if defined(XP_MACOSX)
  1209   FSRef fsRef;
  1210   OSErr err = ::FSFindFolder(kOnSystemDisk, kApplicationSupportFolderType, kCreateFolder, &fsRef);
  1211   NS_ENSURE_FALSE(err, NS_ERROR_FAILURE);
  1213   rv = NS_NewNativeLocalFile(EmptyCString(), true, getter_AddRefs(localDir));
  1214   NS_ENSURE_SUCCESS(rv, rv);
  1216   nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(localDir);
  1217   NS_ENSURE_TRUE(dirFileMac, NS_ERROR_UNEXPECTED);
  1219   rv = dirFileMac->InitWithFSRef(&fsRef);
  1220   NS_ENSURE_SUCCESS(rv, rv);
  1222   localDir = do_QueryInterface(dirFileMac, &rv);
  1224   static const char* const sXR = "Mozilla";
  1225   rv = localDir->AppendNative(nsDependentCString(sXR));
  1226   NS_ENSURE_SUCCESS(rv, rv);
  1228   static const char* const sExtensions = "Extensions";
  1229   rv = localDir->AppendNative(nsDependentCString(sExtensions));
  1230   NS_ENSURE_SUCCESS(rv, rv);
  1231 #elif defined(XP_UNIX)
  1232   static const char *const sysSExtDir = 
  1233 #ifdef HAVE_USR_LIB64_DIR
  1234     "/usr/lib64/mozilla/extensions";
  1235 #elif defined(__OpenBSD__) || defined(__FreeBSD__)
  1236     "/usr/local/lib/mozilla/extensions";
  1237 #else
  1238     "/usr/lib/mozilla/extensions";
  1239 #endif
  1241   rv = NS_NewNativeLocalFile(nsDependentCString(sysSExtDir), false,
  1242                              getter_AddRefs(localDir));
  1243   NS_ENSURE_SUCCESS(rv, rv);
  1244 #endif
  1246   NS_ADDREF(*aFile = localDir);
  1247   return NS_OK;
  1249 #endif
  1251 nsresult
  1252 nsXREDirProvider::GetUserDataDirectory(nsIFile** aFile, bool aLocal,
  1253                                        const nsACString* aProfileName,
  1254                                        const nsACString* aAppName,
  1255                                        const nsACString* aVendorName)
  1257   nsCOMPtr<nsIFile> localDir;
  1258   nsresult rv = GetUserDataDirectoryHome(getter_AddRefs(localDir), aLocal);
  1259   NS_ENSURE_SUCCESS(rv, rv);
  1261   rv = AppendProfilePath(localDir, aProfileName, aAppName, aVendorName, aLocal);
  1262   NS_ENSURE_SUCCESS(rv, rv);
  1264 #ifdef DEBUG_jungshik
  1265   nsAutoCString cwd;
  1266   localDir->GetNativePath(cwd);
  1267   printf("nsXREDirProvider::GetUserDataDirectory: %s\n", cwd.get());
  1268 #endif
  1269   rv = EnsureDirectoryExists(localDir);
  1270   NS_ENSURE_SUCCESS(rv, rv);
  1272   NS_ADDREF(*aFile = localDir);
  1273   return NS_OK;
  1276 nsresult
  1277 nsXREDirProvider::EnsureDirectoryExists(nsIFile* aDirectory)
  1279   bool exists;
  1280   nsresult rv = aDirectory->Exists(&exists);
  1281   NS_ENSURE_SUCCESS(rv, rv);
  1282 #ifdef DEBUG_jungshik
  1283   if (!exists) {
  1284     nsAutoCString cwd;
  1285     aDirectory->GetNativePath(cwd);
  1286     printf("nsXREDirProvider::EnsureDirectoryExists: %s does not\n", cwd.get());
  1288 #endif
  1289   if (!exists)
  1290     rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0700);
  1291 #ifdef DEBUG_jungshik
  1292   if (NS_FAILED(rv))
  1293     NS_WARNING("nsXREDirProvider::EnsureDirectoryExists: create failed");
  1294 #endif
  1296   return rv;
  1299 void
  1300 nsXREDirProvider::EnsureProfileFileExists(nsIFile *aFile)
  1302   nsresult rv;
  1303   bool exists;
  1305   rv = aFile->Exists(&exists);
  1306   if (NS_FAILED(rv) || exists) return;
  1308   nsAutoCString leafName;
  1309   rv = aFile->GetNativeLeafName(leafName);
  1310   if (NS_FAILED(rv)) return;
  1312   nsCOMPtr<nsIFile> defaultsFile;
  1313   rv = GetProfileDefaultsDir(getter_AddRefs(defaultsFile));
  1314   if (NS_FAILED(rv)) return;
  1316   rv = defaultsFile->AppendNative(leafName);
  1317   if (NS_FAILED(rv)) return;
  1319   defaultsFile->CopyToNative(mProfileDir, EmptyCString());
  1322 nsresult
  1323 nsXREDirProvider::GetProfileDefaultsDir(nsIFile* *aResult)
  1325   NS_ASSERTION(mGREDir, "nsXREDirProvider not initialized.");
  1326   NS_PRECONDITION(aResult, "Null out-param");
  1328   nsresult rv;
  1329   nsCOMPtr<nsIFile> defaultsDir;
  1331   rv = GetAppDir()->Clone(getter_AddRefs(defaultsDir));
  1332   NS_ENSURE_SUCCESS(rv, rv);
  1334   rv = defaultsDir->AppendNative(NS_LITERAL_CSTRING("defaults"));
  1335   NS_ENSURE_SUCCESS(rv, rv);
  1337   rv = defaultsDir->AppendNative(NS_LITERAL_CSTRING("profile"));
  1338   NS_ENSURE_SUCCESS(rv, rv);
  1340   NS_ADDREF(*aResult = defaultsDir);
  1341   return NS_OK;
  1344 nsresult
  1345 nsXREDirProvider::AppendSysUserExtensionPath(nsIFile* aFile)
  1347   NS_ASSERTION(aFile, "Null pointer!");
  1349   nsresult rv;
  1351 #if defined (XP_MACOSX) || defined(XP_WIN)
  1353   static const char* const sXR = "Mozilla";
  1354   rv = aFile->AppendNative(nsDependentCString(sXR));
  1355   NS_ENSURE_SUCCESS(rv, rv);
  1357   static const char* const sExtensions = "Extensions";
  1358   rv = aFile->AppendNative(nsDependentCString(sExtensions));
  1359   NS_ENSURE_SUCCESS(rv, rv);
  1361 #elif defined(XP_UNIX)
  1363   static const char* const sXR = ".mozilla";
  1364   rv = aFile->AppendNative(nsDependentCString(sXR));
  1365   NS_ENSURE_SUCCESS(rv, rv);
  1367   static const char* const sExtensions = "extensions";
  1368   rv = aFile->AppendNative(nsDependentCString(sExtensions));
  1369   NS_ENSURE_SUCCESS(rv, rv);
  1371 #else
  1372 #error "Don't know how to get XRE user extension path on your platform"
  1373 #endif
  1374   return NS_OK;
  1378 nsresult
  1379 nsXREDirProvider::AppendProfilePath(nsIFile* aFile,
  1380                                     const nsACString* aProfileName,
  1381                                     const nsACString* aAppName,
  1382                                     const nsACString* aVendorName,
  1383                                     bool aLocal)
  1385   NS_ASSERTION(aFile, "Null pointer!");
  1387   if (!gAppData) {
  1388     return NS_ERROR_FAILURE;
  1391   nsAutoCString profile;
  1392   if (aProfileName && !aProfileName->IsEmpty()) {
  1393     profile = *aProfileName;
  1394   } else if (gAppData->profile) {
  1395     profile = gAppData->profile;
  1398   nsresult rv = NS_ERROR_FAILURE;
  1400 #if defined (XP_MACOSX)
  1401   if (!profile.IsEmpty()) {
  1402     rv = AppendProfileString(aFile, profile.get());
  1403     NS_ENSURE_SUCCESS(rv, rv);
  1406 #elif defined(XP_WIN)
  1407   if (!profile.IsEmpty()) {
  1408     rv = AppendProfileString(aFile, profile.get());
  1409     NS_ENSURE_SUCCESS(rv, rv);
  1412 #elif defined(ANDROID)
  1413   // The directory used for storing profiles
  1414   // The parent of this directory is set in GetUserDataDirectoryHome
  1415   // XXX: handle gAppData->profile properly
  1416   // XXXsmaug ...and the rest of the profile creation!
  1417   MOZ_ASSERT(!aAppName,
  1418              "Profile creation for external applications is not implemented!");
  1419   rv = aFile->AppendNative(nsDependentCString("mozilla"));
  1420   NS_ENSURE_SUCCESS(rv, rv);
  1421 #elif defined(XP_UNIX)
  1422   if (!profile.IsEmpty()) {
  1423     // Skip any leading path characters
  1424     const char* profileStart = profile.get();
  1425     while (*profileStart == '/' || *profileStart == '\\')
  1426       profileStart++;
  1428     // On the off chance that someone wanted their folder to be hidden don't
  1429     // let it become ".."
  1430     if (*profileStart == '.')
  1431       profileStart++;
  1433     // Make it hidden (by starting with ".").
  1434     nsAutoCString folder(".");
  1435     folder.Append(profileStart);
  1436     ToLowerCase(folder);
  1438     rv = AppendProfileString(aFile, folder.BeginReading());
  1439     NS_ENSURE_SUCCESS(rv, rv);
  1442 #else
  1443 #error "Don't know how to get profile path on your platform"
  1444 #endif
  1445   return NS_OK;
  1448 nsresult
  1449 nsXREDirProvider::AppendProfileString(nsIFile* aFile, const char* aPath)
  1451   NS_ASSERTION(aFile, "Null file!");
  1452   NS_ASSERTION(aPath, "Null path!");
  1454   nsAutoCString pathDup(aPath);
  1456   char* path = pathDup.BeginWriting();
  1458   nsresult rv;
  1459   char* subdir;
  1460   while ((subdir = NS_strtok("/\\", &path))) {
  1461     rv = aFile->AppendNative(nsDependentCString(subdir));
  1462     NS_ENSURE_SUCCESS(rv, rv);
  1465   return NS_OK;

mercurial