This is an automated email from the git hooks/post-receive script.
richard pushed a commit to branch tor-browser-102.3.0esr-12.0-2 in repository tor-browser.
commit 6cd742c3080669e9d2a5ab96a5f15ee31d22f3c1 Author: Kathy Brade brade@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 b98668607c9b..7b5752b4c20f 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -2996,6 +2996,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; @@ -4017,6 +4032,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 + mozilla::startup::IncreaseDescriptorLimits();
#ifdef USE_GLX_TEST @@ -4938,7 +4961,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 " @@ -5046,12 +5096,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 0454863ac07a..c39c1fabd57c 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 @@ -1332,7 +1334,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; @@ -1342,6 +1350,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); @@ -1489,6 +1498,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 a9d017d18e0f..f7270905aded 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 000000000000..30a78f18123e --- /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 000000000000..22cae5a660f4 --- /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 a6bcba45515a..152f691ae02b 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 += [ @@ -136,6 +137,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 60b1775eda97..85ce71c5016c 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);