Commit 350024c0 authored by Kathleen Brade's avatar Kathleen Brade Committed by Richard Pospesel
Browse files

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.
parent f9eeb0ed
Loading
Loading
Loading
Loading
+50 −6
Original line number Diff line number Diff line
@@ -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")) {
+22 −1
Original line number Diff line number Diff line
@@ -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;
+6 −0
Original line number Diff line number Diff line
@@ -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.
   *
+96 −0
Original line number Diff line number Diff line
/* -*- 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;
}
+32 −0
Original line number Diff line number Diff line
/* -*- 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__
Loading