Commit 1f2c665f authored by Kathleen Brade's avatar Kathleen Brade Committed by Mike Perry
Browse files

Bug #9173: Change the default Firefox profile directory to be TBB-relative.

This should eliminate our need to rely on a wrapper script that sets $HOME and
launches Firefox with -profile.
parent a565de64
Loading
Loading
Loading
Loading
+34 −119
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include "nsArrayEnumerator.h"
#include "nsEnumeratorUtils.h"
#include "nsReadableUtils.h"
#include "nsXPCOMPrivate.h"  // for XPCOM_FILE_PATH_SEPARATOR
#include "mozilla/Services.h"
#include "mozilla/Omnijar.h"
#include "mozilla/Preferences.h"
@@ -188,9 +189,6 @@ nsXREDirProvider::GetUserProfilesRootDir(nsIFile** aResult,
                                     aProfileName, aAppName, aVendorName);

  if (NS_SUCCEEDED(rv)) {
#if !defined(XP_UNIX) || defined(XP_MACOSX)
    rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
#endif
    // We must create the profile directory here if it does not exist.
    nsresult tmp = EnsureDirectoryExists(file);
    if (NS_FAILED(tmp)) {
@@ -213,9 +211,6 @@ nsXREDirProvider::GetUserProfilesLocalDir(nsIFile** aResult,
                                     aProfileName, aAppName, aVendorName);

  if (NS_SUCCEEDED(rv)) {
#if !defined(XP_UNIX) || defined(XP_MACOSX)
    rv = file->AppendNative(NS_LITERAL_CSTRING("Profiles"));
#endif
    // We must create the profile directory here if it does not exist.
    nsresult tmp = EnsureDirectoryExists(file);
    if (NS_FAILED(tmp)) {
@@ -1143,82 +1138,45 @@ nsresult
nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal)
{
  // Copied from nsAppFileLocationProvider (more or less)
  nsresult rv;
  NS_ENSURE_ARG_POINTER(aFile);
  nsCOMPtr<nsIFile> localDir;

  nsresult rv = GetAppDir()->Clone(getter_AddRefs(localDir));
  NS_ENSURE_SUCCESS(rv, rv);

  int levelsToRemove = 1; // In FF21+, appDir points to browser subdirectory.
#if defined(XP_MACOSX)
  FSRef fsRef;
  OSType folderType;
  if (aLocal) {
    folderType = kCachedDataFolderType;
  } else {
#ifdef MOZ_THUNDERBIRD
    folderType = kDomainLibraryFolderType;
#else
    folderType = kApplicationSupportFolderType;
  levelsToRemove += 2;
#endif
  }
  OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef);
  NS_ENSURE_FALSE(err, NS_ERROR_FAILURE);

  rv = NS_NewNativeLocalFile(EmptyCString(), true, getter_AddRefs(localDir));
  while (localDir && (levelsToRemove > 0)) {
    // When crawling up the hierarchy, components named "." do not count.
    nsAutoCString removedName;
    rv = localDir->GetNativeLeafName(removedName);
    NS_ENSURE_SUCCESS(rv, rv);
    bool didRemove = !removedName.Equals(".");

  nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(localDir);
  NS_ENSURE_TRUE(dirFileMac, NS_ERROR_UNEXPECTED);

  rv = dirFileMac->InitWithFSRef(&fsRef);
    // Remove a directory component.
    nsCOMPtr<nsIFile> parentDir;
    rv = localDir->GetParent(getter_AddRefs(parentDir));
    NS_ENSURE_SUCCESS(rv, rv);
    localDir = parentDir;

  localDir = do_QueryInterface(dirFileMac, &rv);
#elif defined(XP_WIN)
  nsString path;
  if (aLocal) {
    rv = GetShellFolderPath(CSIDL_LOCAL_APPDATA, path);
    if (NS_FAILED(rv))
      rv = GetRegWindowsAppDataFolder(aLocal, path);
  }
  if (!aLocal || NS_FAILED(rv)) {
    rv = GetShellFolderPath(CSIDL_APPDATA, path);
    if (NS_FAILED(rv)) {
      if (!aLocal)
        rv = GetRegWindowsAppDataFolder(aLocal, path);
    }
    if (didRemove)
      --levelsToRemove;
  }
  NS_ENSURE_SUCCESS(rv, rv);

  rv = NS_NewLocalFile(path, true, getter_AddRefs(localDir));
#elif defined(MOZ_WIDGET_GONK)
  rv = NS_NewNativeLocalFile(NS_LITERAL_CSTRING("/data/b2g"), true,
                             getter_AddRefs(localDir));
#elif defined(XP_UNIX)
  const char* homeDir = getenv("HOME");
  if (!homeDir || !*homeDir)
  if (!localDir)
    return NS_ERROR_FAILURE;

#ifdef ANDROID /* We want (ProfD == ProfLD) on Android. */
  aLocal = false;
#endif
  rv = localDir->AppendRelativeNativePath(NS_LITERAL_CSTRING("TorBrowser"
                                     XPCOM_FILE_PATH_SEPARATOR "Data"
                                     XPCOM_FILE_PATH_SEPARATOR "Browser"));
  NS_ENSURE_SUCCESS(rv, rv);

  if (aLocal) {
    // If $XDG_CACHE_HOME is defined use it, otherwise use $HOME/.cache.
    const char* cacheHome = getenv("XDG_CACHE_HOME");
    if (cacheHome && *cacheHome) {
      rv = NS_NewNativeLocalFile(nsDependentCString(cacheHome), true,
                                 getter_AddRefs(localDir));
    } else {
      rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
                                 getter_AddRefs(localDir));
      if (NS_SUCCEEDED(rv))
        rv = localDir->AppendNative(NS_LITERAL_CSTRING(".cache"));
    }
  } else {
    rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
                               getter_AddRefs(localDir));
    rv = localDir->AppendNative(NS_LITERAL_CSTRING("Caches"));
    NS_ENSURE_SUCCESS(rv, rv);
  }
#else
#error "Don't know how to get product dir on your platform"
#endif

  NS_IF_ADDREF(*aFile = localDir);
  return rv;
@@ -1431,48 +1389,25 @@ nsXREDirProvider::AppendProfilePath(nsIFile* aFile,
  }

  nsAutoCString profile;
  nsAutoCString appName;
  nsAutoCString vendor;
  if (aProfileName && !aProfileName->IsEmpty()) {
    profile = *aProfileName;
  } else if (aAppName) {
    appName = *aAppName;
    if (aVendorName) {
      vendor = *aVendorName;
    }
  } else if (gAppData->profile) {
    profile = gAppData->profile;
  } else {
    appName = gAppData->name;
    vendor = gAppData->vendor;
  }

  nsresult rv;
  nsresult rv = NS_ERROR_FAILURE;

#if defined (XP_MACOSX)
  if (!profile.IsEmpty()) {
    rv = AppendProfileString(aFile, profile.get());
  }
  else {
    // Note that MacOS ignores the vendor when creating the profile hierarchy -
    // all application preferences directories live alongside one another in
    // ~/Library/Application Support/
    rv = aFile->AppendNative(appName);
  }
    NS_ENSURE_SUCCESS(rv, rv);
  }

#elif defined(XP_WIN)
  if (!profile.IsEmpty()) {
    rv = AppendProfileString(aFile, profile.get());
  }
  else {
    if (!vendor.IsEmpty()) {
      rv = aFile->AppendNative(vendor);
    NS_ENSURE_SUCCESS(rv, rv);
  }
    rv = aFile->AppendNative(appName);
  }
  NS_ENSURE_SUCCESS(rv, rv);

#elif defined(ANDROID)
  // The directory used for storing profiles
@@ -1484,12 +1419,6 @@ nsXREDirProvider::AppendProfilePath(nsIFile* aFile,
  rv = aFile->AppendNative(nsDependentCString("mozilla"));
  NS_ENSURE_SUCCESS(rv, rv);
#elif defined(XP_UNIX)
  nsAutoCString folder;
  // Make it hidden (by starting with "."), except when local (the
  // profile is already under ~/.cache or XDG_CACHE_HOME).
  if (!aLocal)
    folder.Assign('.');

  if (!profile.IsEmpty()) {
    // Skip any leading path characters
    const char* profileStart = profile.get();
@@ -1498,32 +1427,18 @@ nsXREDirProvider::AppendProfilePath(nsIFile* aFile,

    // On the off chance that someone wanted their folder to be hidden don't
    // let it become ".."
    if (*profileStart == '.' && !aLocal)
    if (*profileStart == '.')
      profileStart++;

    // Make it hidden (by starting with ".").
    nsAutoCString folder(".");
    folder.Append(profileStart);
    ToLowerCase(folder);

    rv = AppendProfileString(aFile, folder.BeginReading());
  }
  else {
    if (!vendor.IsEmpty()) {
      folder.Append(vendor);
      ToLowerCase(folder);

      rv = aFile->AppendNative(folder);
    NS_ENSURE_SUCCESS(rv, rv);

      folder.Truncate();
  }

    folder.Append(appName);
    ToLowerCase(folder);

    rv = aFile->AppendNative(folder);
  }
  NS_ENSURE_SUCCESS(rv, rv);

#else
#error "Don't know how to get profile path on your platform"
#endif
+5 −5
Original line number Diff line number Diff line
@@ -56,16 +56,16 @@ public:

  nsresult GetProfileDefaultsDir(nsIFile* *aResult);

  static nsresult GetUserAppDataDirectory(nsIFile* *aFile) {
  nsresult GetUserAppDataDirectory(nsIFile* *aFile) {
    return GetUserDataDirectory(aFile, false, nullptr, nullptr, nullptr);
  }
  static nsresult GetUserLocalDataDirectory(nsIFile* *aFile) {
  nsresult GetUserLocalDataDirectory(nsIFile* *aFile) {
    return GetUserDataDirectory(aFile, true, nullptr, nullptr, nullptr);
  }

  // By default GetUserDataDirectory gets profile path from gAppData,
  // but that can be overridden by using aProfileName/aAppName/aVendorName.
  static nsresult GetUserDataDirectory(nsIFile** aFile, bool aLocal,
  nsresult GetUserDataDirectory(nsIFile** aFile, bool aLocal,
                                       const nsACString* aProfileName,
                                       const nsACString* aAppName,
                                       const nsACString* aVendorName);
@@ -101,8 +101,8 @@ public:

protected:
  nsresult GetFilesInternal(const char* aProperty, nsISimpleEnumerator** aResult);
  static nsresult GetUserDataDirectoryHome(nsIFile* *aFile, bool aLocal);
  static nsresult GetSysUserExtensionsDirectory(nsIFile* *aFile);
  nsresult GetUserDataDirectoryHome(nsIFile* *aFile, bool aLocal);
  nsresult GetSysUserExtensionsDirectory(nsIFile* *aFile);
#if defined(XP_UNIX) || defined(XP_MACOSX)
  static nsresult GetSystemExtensionsDirectory(nsIFile** aFile);
#endif
+4 −0
Original line number Diff line number Diff line
@@ -126,4 +126,8 @@ FINAL_LIBRARY = 'xpcom_core'
if CONFIG['OS_ARCH'] == 'Linux' and 'lib64' in CONFIG['libdir']:
    DEFINES['HAVE_USR_LIB64_DIR'] = True

LOCAL_INCLUDES += [
    '../build'
]

GENERATED_INCLUDES += ['..']
+38 −43
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include "nsISimpleEnumerator.h"
#include "prenv.h"
#include "nsCRT.h"
#include "nsXPCOMPrivate.h"  // for XPCOM_FILE_PATH_SEPARATOR

#if defined(MOZ_WIDGET_COCOA)
#include <Carbon/Carbon.h>
@@ -284,9 +285,8 @@ NS_METHOD nsAppFileLocationProvider::CloneMozBinDirectory(nsIFile **aLocalFile)
//----------------------------------------------------------------------------------------
// GetProductDirectory - Gets the directory which contains the application data folder
//
// UNIX   : ~/.mozilla/
// WIN    : <Application Data folder on user's machine>\Mozilla
// Mac    : :Documents:Mozilla:
// UNIX and WIN   : <App Folder>/TorBrowser/Data/Browser
// Mac            : <App Folder>/../../TorBrowser/Data/Browser
//----------------------------------------------------------------------------------------
NS_METHOD nsAppFileLocationProvider::GetProductDirectory(nsIFile **aLocalFile, bool aLocal)
{
@@ -297,32 +297,43 @@ NS_METHOD nsAppFileLocationProvider::GetProductDirectory(nsIFile **aLocalFile, b
    bool exists;
    nsCOMPtr<nsIFile> localDir;

#if defined(MOZ_WIDGET_COCOA)
    FSRef fsRef;
    OSType folderType = aLocal ? (OSType) kCachedDataFolderType : (OSType) kDomainLibraryFolderType;
    OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef);
    if (err) return NS_ERROR_FAILURE;
    NS_NewLocalFile(EmptyString(), true, getter_AddRefs(localDir));
    if (!localDir) return NS_ERROR_FAILURE;
    nsCOMPtr<nsILocalFileMac> localDirMac(do_QueryInterface(localDir));
    rv = localDirMac->InitWithFSRef(&fsRef);
    if (NS_FAILED(rv)) return rv;
#elif defined(XP_WIN)
    nsCOMPtr<nsIProperties> directoryService = 
             do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
    if (NS_FAILED(rv)) return rv;
    const char* prop = aLocal ? NS_WIN_LOCAL_APPDATA_DIR : NS_WIN_APPDATA_DIR;
    rv = directoryService->Get(prop, NS_GET_IID(nsIFile), getter_AddRefs(localDir));
    if (NS_FAILED(rv)) return rv;
#elif defined(XP_UNIX)
    rv = NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")), true, getter_AddRefs(localDir));
    if (NS_FAILED(rv)) return rv;
#else
#error dont_know_how_to_get_product_dir_on_your_platform
    rv = CloneMozBinDirectory(getter_AddRefs(localDir));
    NS_ENSURE_SUCCESS(rv, rv);

    int levelsToRemove = 1; // In FF21+, bin dir points to browser subdirectory.
#if defined(XP_MACOSX)
    levelsToRemove += 2;
#endif
    while (localDir && (levelsToRemove > 0)) {
        // When crawling up the hierarchy, components named "." do not count.
        nsAutoCString removedName;
        rv = localDir->GetNativeLeafName(removedName);
        NS_ENSURE_SUCCESS(rv, rv);
        bool didRemove = !removedName.Equals(".");

        // Remove a directory component.
        nsCOMPtr<nsIFile> parentDir;
        rv = localDir->GetParent(getter_AddRefs(parentDir));
        NS_ENSURE_SUCCESS(rv, rv);
        localDir = parentDir;

        if (didRemove)
          --levelsToRemove;
    }

    if (!localDir)
        return NS_ERROR_FAILURE;

    rv = localDir->AppendRelativeNativePath(NS_LITERAL_CSTRING("TorBrowser"
                                       XPCOM_FILE_PATH_SEPARATOR "Data"
                                       XPCOM_FILE_PATH_SEPARATOR "Browser"));
    NS_ENSURE_SUCCESS(rv, rv);

    if (aLocal) {
        rv = localDir->AppendNative(NS_LITERAL_CSTRING("Caches"));
        NS_ENSURE_SUCCESS(rv, rv);
    }

    rv = localDir->AppendRelativeNativePath(DEFAULT_PRODUCT_DIR);
    if (NS_FAILED(rv)) return rv;
    rv = localDir->Exists(&exists);

    if (NS_SUCCEEDED(rv) && !exists)
@@ -339,10 +350,6 @@ NS_METHOD nsAppFileLocationProvider::GetProductDirectory(nsIFile **aLocalFile, b

//----------------------------------------------------------------------------------------
// GetDefaultUserProfileRoot - Gets the directory which contains each user profile dir
//
// UNIX   : ~/.mozilla/
// WIN    : <Application Data folder on user's machine>\Mozilla\Profiles
// Mac    : :Documents:Mozilla:Profiles:
//----------------------------------------------------------------------------------------
NS_METHOD nsAppFileLocationProvider::GetDefaultUserProfileRoot(nsIFile **aLocalFile, bool aLocal)
{
@@ -355,18 +362,6 @@ NS_METHOD nsAppFileLocationProvider::GetDefaultUserProfileRoot(nsIFile **aLocalF
    rv = GetProductDirectory(getter_AddRefs(localDir), aLocal);
    if (NS_FAILED(rv)) return rv;

#if defined(MOZ_WIDGET_COCOA) || defined(XP_WIN)
    // These 3 platforms share this part of the path - do them as one
    rv = localDir->AppendRelativeNativePath(NS_LITERAL_CSTRING("Profiles"));
    if (NS_FAILED(rv)) return rv;

    bool exists;
    rv = localDir->Exists(&exists);
    if (NS_SUCCEEDED(rv) && !exists)
        rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
    if (NS_FAILED(rv)) return rv;
#endif

    *aLocalFile = localDir;
    NS_ADDREF(*aLocalFile);