[tor-commits] [tor-browser/tor-browser-78.13.0esr-10.5-2] Bug 13252: Do not store data in the app bundle

sysrqb at torproject.org sysrqb at torproject.org
Thu Aug 12 15:48:29 UTC 2021


commit f69ab0600930c062b392f4310586c8a083102554
Author: Kathy Brade <brade at pearlcrescent.com>
Date:   Fri Mar 18 14:20:02 2016 -0400

    Bug 13252: Do not store data in the app bundle
    
    When --enable-tor-browser-data-outside-app-dir is enabled,
    all user data is stored in a directory named
    TorBrowser-Data which is located next to the application directory.
    
    Display an informative error message if the TorBrowser-Data
    directory cannot be created due to an "access denied" or a
    "read only volume" error.
    
    On Mac OS, add support for the --invisible command line option which
    is used by the meek-http-helper to avoid showing an icon for the
    helper browser on the dock.
---
 toolkit/xre/nsAppRunner.cpp            |  76 +++++++++++++++---
 toolkit/xre/nsXREDirProvider.cpp       |  43 +++++-----
 toolkit/xre/nsXREDirProvider.h         |   6 ++
 xpcom/io/TorFileUtils.cpp              | 142 +++++++++++++++++++++++++++++++++
 xpcom/io/TorFileUtils.h                |  33 ++++++++
 xpcom/io/moz.build                     |   5 ++
 xpcom/io/nsAppFileLocationProvider.cpp |  53 +++++-------
 7 files changed, 290 insertions(+), 68 deletions(-)

diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
index 8de43a8c4cfc..9854332f6917 100644
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1886,6 +1886,8 @@ static nsresult ProfileMissingDialog(nsINativeAppSupport* aNative) {
   }
 }
 
+// If aUnlocker is NULL, it is also OK for the following arguments to be NULL:
+//   aProfileDir, aProfileLocalDir, aResult.
 static ReturnAbortOnError ProfileErrorDialog(nsIFile* aProfileDir,
                                              nsIFile* aProfileLocalDir,
                                              ProfileStatus aStatus,
@@ -1894,17 +1896,19 @@ static ReturnAbortOnError ProfileErrorDialog(nsIFile* aProfileDir,
                                              nsIProfileLock** aResult) {
   nsresult rv;
 
-  bool exists;
-  aProfileDir->Exists(&exists);
-  if (!exists) {
-    return ProfileMissingDialog(aNative);
+  if (aProfileDir) {
+    bool exists;
+    aProfileDir->Exists(&exists);
+    if (!exists) {
+      return ProfileMissingDialog(aNative);
+    }
   }
 
   ScopedXPCOMStartup xpcom;
   rv = xpcom.Initialize();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  mozilla::Telemetry::WriteFailedProfileLock(aProfileDir);
+  if (aProfileDir) mozilla::Telemetry::WriteFailedProfileLock(aProfileDir);
 
   rv = xpcom.SetWindowCreator(aNative);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
@@ -1994,7 +1998,8 @@ static ReturnAbortOnError ProfileErrorDialog(nsIFile* aProfileDir,
       }
     } else {
 #ifdef MOZ_WIDGET_ANDROID
-      if (java::GeckoAppShell::UnlockProfile()) {
+      if (aProfileDir && aProfileLocalDir && aResult &&
+          java::GeckoAppShell::UnlockProfile()) {
         return NS_LockProfilePath(aProfileDir, aProfileLocalDir, nullptr,
                                   aResult);
       }
@@ -2102,6 +2107,23 @@ static ReturnAbortOnError ShowProfileManager(
   return LaunchChild(false);
 }
 
+#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+static ProfileStatus CheckTorBrowserDataWriteAccess(nsIFile* aAppDir) {
+  // Check whether we can write to the directory that will contain
+  // TorBrowser-Data.
+  nsCOMPtr<nsIFile> tbDataDir;
+  RefPtr<nsXREDirProvider> dirProvider = nsXREDirProvider::GetSingleton();
+  if (!dirProvider) return PROFILE_STATUS_OTHER_ERROR;
+  nsresult rv =
+      dirProvider->GetTorBrowserUserDataDir(getter_AddRefs(tbDataDir));
+  NS_ENSURE_SUCCESS(rv, PROFILE_STATUS_OTHER_ERROR);
+  nsCOMPtr<nsIFile> tbDataDirParent;
+  rv = tbDataDir->GetParent(getter_AddRefs(tbDataDirParent));
+  NS_ENSURE_SUCCESS(rv, PROFILE_STATUS_OTHER_ERROR);
+  return nsToolkitProfileService::CheckProfileWriteAccess(tbDataDirParent);
+}
+#endif
+
 static bool gDoMigration = false;
 static bool gDoProfileReset = false;
 static nsCOMPtr<nsIToolkitProfile> gResetOldProfile;
@@ -3178,6 +3200,14 @@ int XREMain::XRE_mainInit(bool* aExitFlag) {
   if (PR_GetEnv("XRE_MAIN_BREAK")) NS_BREAK();
 #endif
 
+#if defined(XP_MACOSX) && defined(TOR_BROWSER_DATA_OUTSIDE_APP_DIR)
+  bool hideDockIcon = (CheckArg("invisible") == ARG_FOUND);
+  if (hideDockIcon) {
+    ProcessSerialNumber psn = {0, kCurrentProcess};
+    TransformProcessType(&psn, kProcessTransformToBackgroundApplication);
+  }
+#endif
+
   IncreaseDescriptorLimits();
 
 #ifdef USE_GLX_TEST
@@ -4026,7 +4056,34 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) {
     return 0;
   }
 
+#if (defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)) || \
+    defined(TOR_BROWSER_DATA_OUTSIDE_APP_DIR)
+  nsCOMPtr<nsIFile> exeFile, exeDir;
+  bool persistent;
+  rv = mDirProvider.GetFile(XRE_EXECUTABLE_FILE, &persistent,
+                            getter_AddRefs(exeFile));
+  NS_ENSURE_SUCCESS(rv, 1);
+  rv = exeFile->GetParent(getter_AddRefs(exeDir));
+  NS_ENSURE_SUCCESS(rv, 1);
+#endif
+
   rv = NS_NewToolkitProfileService(getter_AddRefs(mProfileSvc));
+#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+  if (NS_FAILED(rv)) {
+    // NS_NewToolkitProfileService() returns a generic NS_ERROR_FAILURE error
+    // if creation of the TorBrowser-Data directory fails due to access denied
+    // or because of a read-only disk volume. Do an extra check here to detect
+    // these errors so we can display an informative error message.
+    ProfileStatus status = CheckTorBrowserDataWriteAccess(exeDir);
+    if ((PROFILE_STATUS_ACCESS_DENIED == status) ||
+        (PROFILE_STATUS_READ_ONLY == status)) {
+      ProfileErrorDialog(nullptr, nullptr, status, nullptr, mNativeApp,
+                         nullptr);
+      return 1;
+    }
+  }
+ #endif
+
   if (rv == NS_ERROR_FILE_ACCESS_DENIED) {
     PR_fprintf(PR_STDERR,
                "Error: Access was denied while trying to open files in "
@@ -4095,7 +4152,6 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) {
 #if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
   // Check for and process any available updates
   nsCOMPtr<nsIFile> updRoot;
-  bool persistent;
   rv = mDirProvider.GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
                             getter_AddRefs(updRoot));
   // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
@@ -4131,12 +4187,6 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) {
   if (CheckArg("test-process-updates")) {
     SaveToEnv("MOZ_TEST_PROCESS_UPDATES=1");
   }
-  nsCOMPtr<nsIFile> exeFile, exeDir;
-  rv = mDirProvider.GetFile(XRE_EXECUTABLE_FILE, &persistent,
-                            getter_AddRefs(exeFile));
-  NS_ENSURE_SUCCESS(rv, 1);
-  rv = exeFile->GetParent(getter_AddRefs(exeDir));
-  NS_ENSURE_SUCCESS(rv, 1);
   ProcessUpdates(mDirProvider.GetGREDir(), exeDir, updRoot, gRestartArgc,
                  gRestartArgv, mAppData->version);
   if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
index f80cb2827349..335a340ea3e9 100644
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -51,6 +51,8 @@
 #  include "nsIPK11Token.h"
 #endif
 
+#include "TorFileUtils.h"
+
 #include <stdlib.h>
 
 #ifdef XP_WIN
@@ -1408,34 +1410,18 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
     return gDataDirHome->Clone(aFile);
   }
 
-  nsresult rv = GetAppDir()->Clone(getter_AddRefs(localDir));
+  nsresult rv = GetTorBrowserUserDataDir(getter_AddRefs(localDir));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  int levelsToRemove = 1;  // In FF21+, appDir 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;
-
+#if !defined(ANDROID)
+#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+  rv = localDir->AppendNative(NS_LITERAL_CSTRING("Browser"));
+#else
   rv = localDir->AppendRelativeNativePath(
-      NS_LITERAL_CSTRING("TorBrowser" XPCOM_FILE_PATH_SEPARATOR
-                         "Data" XPCOM_FILE_PATH_SEPARATOR "Browser"));
+      NS_LITERAL_CSTRING("Data" XPCOM_FILE_PATH_SEPARATOR "Browser"));
+#endif
   NS_ENSURE_SUCCESS(rv, rv);
+#endif
 
   if (aLocal) {
     rv = localDir->AppendNative(NS_LITERAL_CSTRING("Caches"));
@@ -1541,6 +1527,15 @@ nsresult nsXREDirProvider::GetUserDataDirectory(nsIFile** aFile, bool aLocal) {
   return NS_OK;
 }
 
+nsresult nsXREDirProvider::GetTorBrowserUserDataDir(nsIFile** aFile) {
+  NS_ENSURE_ARG_POINTER(aFile);
+  nsCOMPtr<nsIFile> exeFile;
+  bool per = false;
+  nsresult rv = GetFile(XRE_EXECUTABLE_FILE, &per, getter_AddRefs(exeFile));
+  NS_ENSURE_SUCCESS(rv, rv);
+  return TorBrowser_GetUserDataDir(exeFile, aFile);
+}
+
 nsresult nsXREDirProvider::EnsureDirectoryExists(nsIFile* aDirectory) {
   nsresult rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0700);
 
diff --git a/toolkit/xre/nsXREDirProvider.h b/toolkit/xre/nsXREDirProvider.h
index b9678d4ec577..2aa2face5974 100644
--- a/toolkit/xre/nsXREDirProvider.h
+++ b/toolkit/xre/nsXREDirProvider.h
@@ -113,6 +113,12 @@ class nsXREDirProvider final : public nsIDirectoryServiceProvider2,
    */
   nsresult GetProfileDir(nsIFile** aResult);
 
+  /**
+   * Get the TorBrowser user data directory by calling the
+   * TorBrowser_GetUserDataDir() utility function.
+   */
+  nsresult GetTorBrowserUserDataDir(nsIFile** aFile);
+
  protected:
   nsresult GetFilesInternal(const char* aProperty,
                             nsISimpleEnumerator** aResult);
diff --git a/xpcom/io/TorFileUtils.cpp b/xpcom/io/TorFileUtils.cpp
new file mode 100644
index 000000000000..bddf8d7bbd95
--- /dev/null
+++ b/xpcom/io/TorFileUtils.cpp
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "TorFileUtils.h"
+#include "nsString.h"
+#ifdef MOZ_WIDGET_COCOA
+#include <Carbon/Carbon.h>
+#include "nsILocalFileMac.h"
+#endif
+
+static nsresult GetAppRootDir(nsIFile *aExeFile, nsIFile** aFile);
+
+//-----------------------------------------------------------------------------
+nsresult
+TorBrowser_GetUserDataDir(nsIFile *aExeFile, nsIFile** aFile)
+{
+  NS_ENSURE_ARG_POINTER(aFile);
+  nsCOMPtr<nsIFile> tbDataDir;
+
+#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+  nsAutoCString tbDataLeafName(NS_LITERAL_CSTRING("TorBrowser-Data"));
+  nsCOMPtr<nsIFile> appRootDir;
+  nsresult rv = GetAppRootDir(aExeFile, getter_AddRefs(appRootDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+#ifndef XP_MACOSX
+  // On all platforms except Mac OS, we always operate in a "portable" mode
+  // where the TorBrowser-Data directory is located next to the application.
+  rv = appRootDir->GetParent(getter_AddRefs(tbDataDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = tbDataDir->AppendNative(tbDataLeafName);
+  NS_ENSURE_SUCCESS(rv, rv);
+#else
+  // For Mac OS, determine whether we should store user data in the OS's
+  // standard location (i.e., under ~/Library/Application Support). We use
+  // the OS location if (1) the application is installed in a directory whose
+  // path contains "/Applications" or (2) the TorBrowser-Data directory does
+  // not exist and cannot be created (which probably means we lack write
+  // permission to the directory that contains the application).
+  nsAutoString appRootPath;
+  rv = appRootDir->GetPath(appRootPath);
+  NS_ENSURE_SUCCESS(rv, rv);
+  bool useOSLocation = (appRootPath.Find("/Applications",
+                                         true /* ignore case */) >= 0);
+  if (!useOSLocation) {
+    // We hope to use the portable (aka side-by-side) approach, but before we
+    // commit to that, let's ensure that we can create the TorBrowser-Data
+    // directory. If it already exists, we will try to use it; if not and we
+    // fail to create it, we will switch to ~/Library/Application Support.
+    rv = appRootDir->GetParent(getter_AddRefs(tbDataDir));
+    NS_ENSURE_SUCCESS(rv, rv);
+    rv = tbDataDir->AppendNative(tbDataLeafName);
+    NS_ENSURE_SUCCESS(rv, rv);
+    bool exists = false;
+    rv = tbDataDir->Exists(&exists);
+    if (NS_SUCCEEDED(rv) && !exists)
+      rv = tbDataDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
+    useOSLocation = NS_FAILED(rv);
+  }
+
+  if (useOSLocation) {
+    // We are using ~/Library/Application Support/TorBrowser-Data. We do not
+    // need to create that directory here because the code in nsXREDirProvider
+    // will do so (and the user should always have write permission for
+    // ~/Library/Application Support; if they do not we have no more options).
+    FSRef fsRef;
+    OSErr err = ::FSFindFolder(kUserDomain, kApplicationSupportFolderType,
+                               kCreateFolder, &fsRef);
+    NS_ENSURE_FALSE(err, NS_ERROR_FAILURE);
+    // To convert the FSRef returned by FSFindFolder() into an nsIFile that
+    // points to ~/Library/Application Support, we first create an empty
+    // nsIFile object (no path) and then use InitWithFSRef() to set the
+    // path.
+    rv = NS_NewNativeLocalFile(EmptyCString(), true,
+                               getter_AddRefs(tbDataDir));
+    NS_ENSURE_SUCCESS(rv, rv);
+    nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(tbDataDir);
+    if (!dirFileMac)
+      return NS_ERROR_UNEXPECTED;
+    rv = dirFileMac->InitWithFSRef(&fsRef);
+    NS_ENSURE_SUCCESS(rv, rv);
+    rv = tbDataDir->AppendNative(tbDataLeafName);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+#endif
+
+#elif defined(ANDROID)
+  // Tor Browser Android stores data in the app home directory.
+  const char* homeDir = getenv("HOME");
+  if (!homeDir || !*homeDir)
+    return NS_ERROR_FAILURE;
+  nsresult rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
+                                      getter_AddRefs(tbDataDir));
+#else
+  // User data is embedded within the application directory (i.e.,
+  // TOR_BROWSER_DATA_OUTSIDE_APP_DIR is not defined).
+  nsresult rv = GetAppRootDir(aExeFile, getter_AddRefs(tbDataDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = tbDataDir->AppendNative(NS_LITERAL_CSTRING("TorBrowser"));
+  NS_ENSURE_SUCCESS(rv, rv);
+#endif
+
+  tbDataDir.forget(aFile);
+  return NS_OK;
+}
+
+static nsresult
+GetAppRootDir(nsIFile *aExeFile, nsIFile** aFile)
+{
+  NS_ENSURE_ARG_POINTER(aExeFile);
+  NS_ENSURE_ARG_POINTER(aFile);
+  nsCOMPtr<nsIFile> appRootDir = aExeFile;
+
+  int levelsToRemove = 1; // Remove firefox (the executable file).
+#if defined(XP_MACOSX)
+  levelsToRemove += 2;   // On Mac OS, we must also remove Contents/MacOS.
+#endif
+  while (appRootDir && (levelsToRemove > 0)) {
+    // When crawling up the hierarchy, components named "." do not count.
+    nsAutoCString removedName;
+    nsresult rv = appRootDir->GetNativeLeafName(removedName);
+    NS_ENSURE_SUCCESS(rv, rv);
+    bool didRemove = !removedName.Equals(".");
+
+    // Remove a directory component.
+    nsCOMPtr<nsIFile> parentDir;
+    rv = appRootDir->GetParent(getter_AddRefs(parentDir));
+    NS_ENSURE_SUCCESS(rv, rv);
+    appRootDir = parentDir;
+
+    if (didRemove)
+      --levelsToRemove;
+  }
+
+  if (!appRootDir)
+    return NS_ERROR_FAILURE;
+
+  appRootDir.forget(aFile);
+  return NS_OK;
+}
diff --git a/xpcom/io/TorFileUtils.h b/xpcom/io/TorFileUtils.h
new file mode 100644
index 000000000000..d5e86abf9685
--- /dev/null
+++ b/xpcom/io/TorFileUtils.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef TorFileUtils_h__
+#define TorFileUtils_h__
+
+#include "nsIFile.h"
+
+/**
+ * TorBrowser_GetUserDataDir
+ *
+ * Retrieve the Tor Browser user data directory.
+ * When built with --enable-tor-browser-data-outside-app-dir, the directory
+ * is next to the application directory, except on Mac OS where it may be
+ * there or it may be at ~/Library/Application Support/TorBrowser-Data (the
+ * latter location is used if the .app bundle is in a directory whose path
+ * contains /Applications or if we lack write access to the directory that
+ * contains the .app).
+ * When built without --enable-tor-browser-data-outside-app-dir, this
+ * directory is TorBrowser.app/TorBrowser.
+ *
+ * @param aExeFile  The firefox executable.
+ * @param aFile     Out parameter that is set to the Tor Browser user data
+ *                  directory.
+ * @return NS_OK on success.  Error otherwise.
+ */
+extern nsresult
+TorBrowser_GetUserDataDir(nsIFile *aExeFile, nsIFile** aFile);
+
+#endif // !TorFileUtils_h__
diff --git a/xpcom/io/moz.build b/xpcom/io/moz.build
index a165b491bc56..b0eb74f4c56d 100644
--- a/xpcom/io/moz.build
+++ b/xpcom/io/moz.build
@@ -86,6 +86,7 @@ EXPORTS += [
     'nsUnicharInputStream.h',
     'nsWildCard.h',
     'SpecialSystemDirectory.h',
+    'TorFileUtils.h',
 ]
 
 EXPORTS.mozilla += [
@@ -135,6 +136,10 @@ UNIFIED_SOURCES += [
     'SpecialSystemDirectory.cpp',
 ]
 
+SOURCES += [
+    'TorFileUtils.cpp',
+]
+
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     SOURCES += [
         'CocoaFileUtils.mm',
diff --git a/xpcom/io/nsAppFileLocationProvider.cpp b/xpcom/io/nsAppFileLocationProvider.cpp
index 81551a8e3893..9f95e5cbec2d 100644
--- a/xpcom/io/nsAppFileLocationProvider.cpp
+++ b/xpcom/io/nsAppFileLocationProvider.cpp
@@ -28,6 +28,8 @@
 #  include <sys/param.h>
 #endif
 
+#include "TorFileUtils.h"
+
 // WARNING: These hard coded names need to go away. They need to
 // come from localizable resources
 
@@ -234,8 +236,14 @@ nsresult nsAppFileLocationProvider::CloneMozBinDirectory(nsIFile** aLocalFile) {
 // GetProductDirectory - Gets the directory which contains the application data
 // folder
 //
+#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+// UNIX and WIN   : <App Folder>/../TorBrowser-Data/Browser
+// Mac            : <App Folder>/../../../TorBrowser-Data/Browser OR
+//                  ~/Library/Application Support/TorBrowser-Data/Browser
+#else
 // UNIX and WIN   : <App Folder>/TorBrowser/Data/Browser
 // Mac            : <App Folder>/../../TorBrowser/Data/Browser
+#endif
 //----------------------------------------------------------------------------------------
 nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
                                                         bool aLocal) {
@@ -243,42 +251,25 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
     return NS_ERROR_INVALID_ARG;
   }
 
-  nsresult rv;
+  nsresult rv = NS_ERROR_UNEXPECTED;
   bool exists;
-  nsCOMPtr<nsIFile> localDir;
+  nsCOMPtr<nsIFile> localDir, exeFile;
 
-  rv = CloneMozBinDirectory(getter_AddRefs(localDir));
+  nsCOMPtr<nsIProperties> directoryService(
+      do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = directoryService->Get(XRE_EXECUTABLE_FILE, NS_GET_IID(nsIFile),
+                             getter_AddRefs(exeFile));
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = TorBrowser_GetUserDataDir(exeFile, 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;
-  }
-
+#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+  rv = localDir->AppendNative(NS_LITERAL_CSTRING("Browser"));
+#else
   rv = localDir->AppendRelativeNativePath(
-      NS_LITERAL_CSTRING("TorBrowser" XPCOM_FILE_PATH_SEPARATOR
-                         "Data" XPCOM_FILE_PATH_SEPARATOR "Browser"));
+      NS_LITERAL_CSTRING("Data" XPCOM_FILE_PATH_SEPARATOR "Browser"));
+#endif
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aLocal) {





More information about the tor-commits mailing list