From e31ee60cc71fab1d7e0e2d29fece781607aa7a86 Mon Sep 17 00:00:00 2001 From: Kathy Brade Date: Fri, 18 Mar 2016 14:20:02 -0400 Subject: [PATCH] Bug 13252: Do not store data in the app bundle Add an --enable-tor-browser-data-outside-app-dir configure option. When this 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. --- .mozconfig-mac | 2 + build/moz.configure/old.configure | 1 + old-configure.in | 12 +++ toolkit/xre/nsAppRunner.cpp | 66 ++++++++++-- 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 ++++----- 10 files changed, 299 insertions(+), 64 deletions(-) create mode 100644 xpcom/io/TorFileUtils.cpp create mode 100644 xpcom/io/TorFileUtils.h diff --git a/.mozconfig-mac b/.mozconfig-mac index dc8cff3028f63..064e62ec7743d 100644 --- a/.mozconfig-mac +++ b/.mozconfig-mac @@ -40,6 +40,8 @@ ac_add_options --enable-official-branding ac_add_options --enable-optimize ac_add_options --disable-debug +ac_add_options --enable-tor-browser-data-outside-app-dir + ac_add_options --disable-crashreporter ac_add_options --disable-webrtc ac_add_options --disable-tests diff --git a/build/moz.configure/old.configure b/build/moz.configure/old.configure index f30c2da045ec7..9271ab2629dc4 100644 --- a/build/moz.configure/old.configure +++ b/build/moz.configure/old.configure @@ -263,6 +263,7 @@ def old_configure_options(*options): '--x-libraries', # Tor additions. + '--enable-tor-browser-data-outside-app-dir', '--enable-tor-launcher', ) def prepare_configure_options(extra_old_configure_args, all_options, *options): diff --git a/old-configure.in b/old-configure.in index 703e0f277591e..036e433abd5f8 100644 --- a/old-configure.in +++ b/old-configure.in @@ -2193,6 +2193,18 @@ fi dnl ======================================================== dnl Tor additions dnl ======================================================== +MOZ_ARG_ENABLE_BOOL(tor-browser-data-outside-app-dir, +[ --enable-tor-browser-data-outside-app-dir + Enable Tor Browser data outside of app directory], + TOR_BROWSER_DATA_OUTSIDE_APP_DIR=1, + TOR_BROWSER_DATA_OUTSIDE_APP_DIR= ) + +if test -n "$TOR_BROWSER_DATA_OUTSIDE_APP_DIR"; then + AC_DEFINE(TOR_BROWSER_DATA_OUTSIDE_APP_DIR) +fi + +AC_SUBST(TOR_BROWSER_DATA_OUTSIDE_APP_DIR) + MOZ_ARG_DISABLE_BOOL(tor-launcher, [ --disable-tor-launcher Do not include Tor Launcher], diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index a4b5a86093c01..f7d718e164163 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -1800,6 +1800,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, @@ -1818,7 +1820,7 @@ static ReturnAbortOnError ProfileErrorDialog(nsIFile* aProfileDir, 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); @@ -1908,7 +1910,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); } @@ -2020,6 +2023,23 @@ static ReturnAbortOnError ShowProfileManager( return LaunchChild(aNative); } +#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 tbDataDir; + RefPtr 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 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 gResetOldProfile; @@ -3192,6 +3212,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 @@ -4057,7 +4085,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 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 " @@ -4124,7 +4179,6 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) { #if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID) // Check for and process any available updates nsCOMPtr 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 @@ -4160,12 +4214,6 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) { if (CheckArg("test-process-updates")) { SaveToEnv("MOZ_TEST_PROCESS_UPDATES=1"); } - nsCOMPtr 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 c11fc7e9dfe43..29a055ee7d95e 100644 --- a/toolkit/xre/nsXREDirProvider.cpp +++ b/toolkit/xre/nsXREDirProvider.cpp @@ -47,6 +47,8 @@ #include "mozilla/Preferences.h" #include "mozilla/Telemetry.h" +#include "TorFileUtils.h" + #include #ifdef XP_WIN @@ -1396,34 +1398,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 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")); @@ -1524,6 +1510,15 @@ nsresult nsXREDirProvider::GetUserDataDirectory(nsIFile** aFile, bool aLocal) { return NS_OK; } +nsresult nsXREDirProvider::GetTorBrowserUserDataDir(nsIFile** aFile) { + NS_ENSURE_ARG_POINTER(aFile); + nsCOMPtr 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) { bool exists; nsresult rv = aDirectory->Exists(&exists); diff --git a/toolkit/xre/nsXREDirProvider.h b/toolkit/xre/nsXREDirProvider.h index c76b778f567e8..a13daac770a35 100644 --- a/toolkit/xre/nsXREDirProvider.h +++ b/toolkit/xre/nsXREDirProvider.h @@ -112,6 +112,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 0000000000000..bddf8d7bbd95a --- /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 +#include "nsILocalFileMac.h" +#endif + +static nsresult GetAppRootDir(nsIFile *aExeFile, nsIFile** aFile); + +//----------------------------------------------------------------------------- +nsresult +TorBrowser_GetUserDataDir(nsIFile *aExeFile, nsIFile** aFile) +{ + NS_ENSURE_ARG_POINTER(aFile); + nsCOMPtr tbDataDir; + +#ifdef TOR_BROWSER_DATA_OUTSIDE_APP_DIR + nsAutoCString tbDataLeafName(NS_LITERAL_CSTRING("TorBrowser-Data")); + nsCOMPtr 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 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 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 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 0000000000000..d5e86abf96851 --- /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 ccf895cca501d..5c313f7cd1cb3 100644 --- a/xpcom/io/moz.build +++ b/xpcom/io/moz.build @@ -85,6 +85,7 @@ EXPORTS += [ 'nsUnicharInputStream.h', 'nsWildCard.h', 'SpecialSystemDirectory.h', + 'TorFileUtils.h', ] EXPORTS.mozilla += [ @@ -134,6 +135,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 9f2656e4b90a1..273a509877d28 100644 --- a/xpcom/io/nsAppFileLocationProvider.cpp +++ b/xpcom/io/nsAppFileLocationProvider.cpp @@ -27,6 +27,8 @@ # include #endif +#include "TorFileUtils.h" + // WARNING: These hard coded names need to go away. They need to // come from localizable resources @@ -248,8 +250,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 : /../TorBrowser-Data/Browser +// Mac : /../../../TorBrowser-Data/Browser OR +// ~/Library/Application Support/TorBrowser-Data/Browser +#else // UNIX and WIN : /TorBrowser/Data/Browser // Mac : /../../TorBrowser/Data/Browser +#endif //---------------------------------------------------------------------------------------- nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile, bool aLocal) { @@ -257,42 +265,25 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile, return NS_ERROR_INVALID_ARG; } - nsresult rv; + nsresult rv = NS_ERROR_UNEXPECTED; bool exists; - nsCOMPtr localDir; + nsCOMPtr localDir, exeFile; - rv = CloneMozBinDirectory(getter_AddRefs(localDir)); + nsCOMPtr 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 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) { -- GitLab