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

sysrqb at torproject.org sysrqb at torproject.org
Fri Feb 19 04:03:53 UTC 2021


commit 0e414888eca024dd512395576c9433f18851cd23
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              | 133 +++++++++++++++++++++++++++++++++
 xpcom/io/TorFileUtils.h                |  32 ++++++++
 xpcom/io/moz.build                     |   5 ++
 xpcom/io/nsAppFileLocationProvider.cpp |  53 ++++++-------
 7 files changed, 280 insertions(+), 68 deletions(-)

diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
index ff2a0ebf8879..9e34295e8119 100644
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -2401,6 +2401,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,
@@ -2409,17 +2411,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);
@@ -2509,7 +2513,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);
       }
@@ -2618,6 +2623,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;
@@ -3644,6 +3666,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
@@ -4507,7 +4537,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 "
@@ -4576,7 +4633,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
@@ -4612,12 +4668,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 11e591a95385..ecd6499bae31 100644
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -48,6 +48,8 @@
 #include "mozilla/XREAppData.h"
 #include "nsPrintfCString.h"
 
+#include "TorFileUtils.h"
+
 #include <stdlib.h>
 
 #ifdef XP_WIN
@@ -1401,34 +1403,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;
-
-  rv = localDir->AppendRelativeNativePath("TorBrowser" XPCOM_FILE_PATH_SEPARATOR
-                                          "Data" XPCOM_FILE_PATH_SEPARATOR
+#if !defined(ANDROID)
+#  ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+  rv = localDir->AppendNative("Browser"_ns);
+#  else
+  rv = localDir->AppendRelativeNativePath("Data" XPCOM_FILE_PATH_SEPARATOR
                                           "Browser"_ns);
+#  endif
   NS_ENSURE_SUCCESS(rv, rv);
+#endif
 
   if (aLocal) {
     rv = localDir->AppendNative("Caches"_ns);
@@ -1534,6 +1520,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..6bd03f1f7fed
--- /dev/null
+++ b/xpcom/io/TorFileUtils.cpp
@@ -0,0 +1,133 @@
+/* -*- 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("TorBrowser-Data"_ns);
+  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(""_ns, 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("TorBrowser"_ns);
+  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..31e70a7e0d3a
--- /dev/null
+++ b/xpcom/io/TorFileUtils.h
@@ -0,0 +1,32 @@
+/* -*- 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 ee6c90fd4b23..2a83efc23be8 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 2bbcee92aedb..66f6940beff6 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;
-  }
-
-  rv = localDir->AppendRelativeNativePath("TorBrowser" XPCOM_FILE_PATH_SEPARATOR
-                                          "Data" XPCOM_FILE_PATH_SEPARATOR
+#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+  rv = localDir->AppendNative("Browser"_ns);
+#else
+  rv = localDir->AppendRelativeNativePath("Data" XPCOM_FILE_PATH_SEPARATOR
                                           "Browser"_ns);
+#endif
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aLocal) {





More information about the tor-commits mailing list