[tor-commits] [tor-browser] 47/72: Bug 13252: Do not store data in the app bundle

gitolite role git at cupani.torproject.org
Fri Jul 8 22:29:32 UTC 2022


This is an automated email from the git hooks/post-receive script.

richard pushed a commit to branch tor-browser-91.11.0esr-11.5-1
in repository tor-browser.

commit a90841e1e0d8fc073dd9b60d7331aa37ad4bdf61
Author: Kathy Brade <brade at pearlcrescent.com>
AuthorDate: 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            | 56 +++++++++++++++++---
 toolkit/xre/nsXREDirProvider.cpp       | 23 +++++++-
 toolkit/xre/nsXREDirProvider.h         |  6 +++
 xpcom/io/TorFileUtils.cpp              | 96 ++++++++++++++++++++++++++++++++++
 xpcom/io/TorFileUtils.h                | 32 ++++++++++++
 xpcom/io/moz.build                     |  5 ++
 xpcom/io/nsAppFileLocationProvider.cpp | 13 ++++-
 7 files changed, 223 insertions(+), 8 deletions(-)

diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
index acc92392cf239..90bf00811b646 100644
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -2587,6 +2587,21 @@ static ReturnAbortOnError ShowProfileManager(
   return LaunchChild(false, true);
 }
 
+#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;
+  nsresult rv =
+      nsXREDirProvider::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;
@@ -3616,6 +3631,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
@@ -4462,7 +4485,34 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) {
   }
 #endif
 
+#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 "
@@ -4568,12 +4618,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 4360b23c820fe..85f84278d886b 100644
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -56,6 +56,8 @@
 #  include "nsIPK11Token.h"
 #endif
 
+#include "TorFileUtils.h"
+
 #include <stdlib.h>
 
 #ifdef XP_WIN
@@ -1375,7 +1377,13 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
     return gDataDirHome->Clone(aFile);
   }
 
-#if defined(RELATIVE_PROFILE_DIRECTORY)
+#if defined(RELATIVE_PROFILE_DIRECTORY) || \
+    defined(TOR_BROWSER_DATA_OUTSIDE_APP_DIR)
+#  ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+  rv = GetTorBrowserUserDataDir(getter_AddRefs(localDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = localDir->AppendNative("Browser"_ns);
+#  else
   RefPtr<nsXREDirProvider> singleton = GetSingleton();
   if (!singleton) {
     return NS_ERROR_OUT_OF_MEMORY;
@@ -1385,6 +1393,7 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile,
   nsAutoCString profileDir(RELATIVE_PROFILE_DIRECTORY);
   rv = localDir->SetRelativePath(localDir.get(), profileDir);
   NS_ENSURE_SUCCESS(rv, rv);
+#endif
   if (aLocal) {
     rv = localDir->AppendNative("Caches"_ns);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -1563,6 +1572,18 @@ nsresult nsXREDirProvider::GetUserDataDirectory(nsIFile** aFile, bool aLocal) {
   return NS_OK;
 }
 
+nsresult nsXREDirProvider::GetTorBrowserUserDataDir(nsIFile** aFile) {
+  NS_ENSURE_ARG_POINTER(aFile);
+  nsCOMPtr<nsIFile> appRootDir;
+  RefPtr<nsXREDirProvider> singleton = GetSingleton();
+  if (!singleton) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  nsresult rv = singleton->GetAppRootDir(getter_AddRefs(appRootDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+  return TorBrowser_GetUserDataDir(appRootDir, aFile);
+}
+
 nsresult nsXREDirProvider::GetAppRootDir(nsIFile** aFile) {
   bool persistent = false;
   nsCOMPtr<nsIFile> file, appRootDir;
diff --git a/toolkit/xre/nsXREDirProvider.h b/toolkit/xre/nsXREDirProvider.h
index a76b087d785a3..2e6e3339ed15a 100644
--- a/toolkit/xre/nsXREDirProvider.h
+++ b/toolkit/xre/nsXREDirProvider.h
@@ -109,6 +109,12 @@ class nsXREDirProvider final : public nsIDirectoryServiceProvider2,
    */
   nsresult GetProfileDir(nsIFile** aResult);
 
+  /**
+   * Get the TorBrowser user data directory by calling the
+   * TorBrowser_GetUserDataDir() utility function.
+   */
+  static nsresult GetTorBrowserUserDataDir(nsIFile** aFile);
+
   /**
    * Get the path to the base application directory.
    *
diff --git a/xpcom/io/TorFileUtils.cpp b/xpcom/io/TorFileUtils.cpp
new file mode 100644
index 0000000000000..30a78f18123e5
--- /dev/null
+++ b/xpcom/io/TorFileUtils.cpp
@@ -0,0 +1,96 @@
+/* -*- 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
+
+nsresult TorBrowser_GetUserDataDir(nsIFile* aAppDir, nsIFile** aFile) {
+  NS_ENSURE_ARG_POINTER(aFile);
+  nsCOMPtr<nsIFile> tbDataDir;
+
+#ifdef ANDROID
+  const char* homeDir = getenv("HOME");
+  if (!homeDir || !*homeDir) return NS_ERROR_FAILURE;
+  nsresult rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true,
+                                      getter_AddRefs(tbDataDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+#elif defined(TOR_BROWSER_DATA_OUTSIDE_APP_DIR)
+  nsAutoCString tbDataLeafName("TorBrowser-Data"_ns);
+#  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.
+  nsresult rv = aAppDir->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;
+  nsresult rv = aAppDir->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 = aAppDir->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
+
+#else
+  // User data is embedded within the application directory (i.e.,
+  // TOR_BROWSER_DATA_OUTSIDE_APP_DIR is not defined).
+  nsresult rv = aAppDir->Clone(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;
+}
diff --git a/xpcom/io/TorFileUtils.h b/xpcom/io/TorFileUtils.h
new file mode 100644
index 0000000000000..22cae5a660f46
--- /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 aAppDir   The path to Tor Browser directory
+ * @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* aAppDir, nsIFile** aFile);
+
+#endif  // !TorFileUtils_h__
diff --git a/xpcom/io/moz.build b/xpcom/io/moz.build
index d28c426e7bd73..af7b5be04f6ee 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 += [
@@ -137,6 +138,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 60b1775eda971..85ce71c5016c4 100644
--- a/xpcom/io/nsAppFileLocationProvider.cpp
+++ b/xpcom/io/nsAppFileLocationProvider.cpp
@@ -27,6 +27,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
 
@@ -247,7 +249,8 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
   bool exists;
   nsCOMPtr<nsIFile> localDir;
 
-#if defined(RELATIVE_PROFILE_DIRECTORY)
+#if defined(RELATIVE_PROFILE_DIRECTORY) || \
+    defined(TOR_BROWSER_DATA_OUTSIDE_APP_DIR)
   nsCOMPtr<nsIProperties> directoryService(
       do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -269,10 +272,18 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile,
     file = appRootDir;
   }
 
+#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR
+  rv = TorBrowser_GetUserDataDir(appRootDir, getter_AddRefs(localDir));
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = localDir->AppendNative("Browser"_ns);
+#else
   localDir = appRootDir;
   nsAutoCString profileDir(RELATIVE_PROFILE_DIRECTORY);
   rv = localDir->SetRelativePath(localDir.get(), profileDir);
   NS_ENSURE_SUCCESS(rv, rv);
+#endif
+
+  NS_ENSURE_SUCCESS(rv, rv);
 
   if (aLocal) {
     rv = localDir->AppendNative("Caches"_ns);

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the tor-commits mailing list