lists.torproject.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

tbb-commits

Thread Start a new thread
Threads by month
  • ----- 2026 -----
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2021 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2020 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2019 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2018 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2017 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2016 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2015 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2014 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
tbb-commits@lists.torproject.org

  • 1 participants
  • 21316 discussions
[tor-browser/tor-browser-84.0-10.5-1] Bug 13252: Do not store data in the app bundle
by sysrqb@torproject.org 09 Dec '20

09 Dec '20
commit c317e84a41b6ed8e700cd9535e93afd2ce8573fb Author: Kathy Brade <brade(a)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 21c5415a5dff..51a1a43ec891 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -2369,6 +2369,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, @@ -2377,17 +2379,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); @@ -2477,7 +2481,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); } @@ -2586,6 +2591,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; @@ -3610,6 +3632,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 @@ -4458,7 +4488,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 " @@ -4527,7 +4584,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 @@ -4563,12 +4619,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 b88fd3eb368c..b2ea009553ad 100644 --- a/toolkit/xre/nsXREDirProvider.cpp +++ b/toolkit/xre/nsXREDirProvider.cpp @@ -46,6 +46,8 @@ #include "mozilla/Telemetry.h" #include "nsPrintfCString.h" +#include "TorFileUtils.h" + #include <stdlib.h> #ifdef XP_WIN @@ -1399,34 +1401,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); @@ -1532,6 +1518,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) {
1 0
0 0
[tor-browser/tor-browser-84.0-10.5-1] Bug 14631: Improve profile access error messages.
by sysrqb@torproject.org 09 Dec '20

09 Dec '20
commit a7a03adb46be84fb44add84c7462b268bd3edbe1 Author: Kathy Brade <brade(a)pearlcrescent.com> Date: Tue Feb 24 13:50:23 2015 -0500 Bug 14631: Improve profile access error messages. Instead of always reporting that the profile is locked, display specific messages for "access denied" and "read-only file system". To allow for localization, get profile-related error strings from Torbutton. Use app display name ("Tor Browser") in profile-related error alerts. --- .../mozapps/profile/profileSelection.properties | 5 + toolkit/profile/nsToolkitProfileService.cpp | 57 +++++++- toolkit/profile/nsToolkitProfileService.h | 13 +- toolkit/xre/nsAppRunner.cpp | 157 ++++++++++++++++++--- 4 files changed, 208 insertions(+), 24 deletions(-) diff --git a/toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties b/toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties index d326083202b2..aa38bda24347 100644 --- a/toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties +++ b/toolkit/locales/en-US/chrome/mozapps/profile/profileSelection.properties @@ -12,6 +12,11 @@ restartMessageUnlocker=%S is already running, but is not responding. The old %S restartMessageNoUnlockerMac=A copy of %S is already open. Only one copy of %S can be open at a time. restartMessageUnlockerMac=A copy of %S is already open. The running copy of %S will quit in order to open this one. +# LOCALIZATION NOTE (profileProblemTitle, profileReadOnly, profileReadOnlyMac, profileAccessDenied): Messages displayed when the browser profile cannot be accessed or written to. %S is the application name. +profileProblemTitle=%S Profile Problem +profileReadOnly=You cannot run %S from a read-only file system. Please copy %S to another location before trying to use it. +profileReadOnlyMac=You cannot run %S from a read-only file system. Please copy %S to your Desktop or Applications folder before trying to use it. +profileAccessDenied=%S does not have permission to access the profile. Please adjust your file system permissions and try again. # Profile manager # LOCALIZATION NOTE (profileTooltip): First %S is the profile name, second %S is the path to the profile folder. profileTooltip=Profile: ‘%S’ — Path: ‘%S’ diff --git a/toolkit/profile/nsToolkitProfileService.cpp b/toolkit/profile/nsToolkitProfileService.cpp index 060248c42689..65066f3562de 100644 --- a/toolkit/profile/nsToolkitProfileService.cpp +++ b/toolkit/profile/nsToolkitProfileService.cpp @@ -1159,9 +1159,10 @@ nsToolkitProfileService::SelectStartupProfile( } bool wasDefault; + ProfileStatus profileStatus; nsresult rv = SelectStartupProfile(&argc, argv.get(), aIsResetting, aRootDir, aLocalDir, - aProfile, aDidCreate, &wasDefault); + aProfile, aDidCreate, &wasDefault, profileStatus); // Since we were called outside of the normal startup path complete any // startup tasks. @@ -1194,7 +1195,8 @@ nsToolkitProfileService::SelectStartupProfile( nsresult nsToolkitProfileService::SelectStartupProfile( int* aArgc, char* aArgv[], bool aIsResetting, nsIFile** aRootDir, nsIFile** aLocalDir, nsIToolkitProfile** aProfile, bool* aDidCreate, - bool* aWasDefaultSelection) { + bool* aWasDefaultSelection, ProfileStatus& aProfileStatus) { + aProfileStatus = PROFILE_STATUS_OK; if (mStartupProfileSelected) { return NS_ERROR_ALREADY_INITIALIZED; } @@ -1288,6 +1290,13 @@ nsresult nsToolkitProfileService::SelectStartupProfile( rv = XRE_GetFileFromPath(arg, getter_AddRefs(lf)); NS_ENSURE_SUCCESS(rv, rv); + aProfileStatus = CheckProfileWriteAccess(lf); + if (PROFILE_STATUS_OK != aProfileStatus) { + NS_ADDREF(*aRootDir = lf); + NS_ADDREF(*aLocalDir = lf); + return NS_ERROR_FAILURE; + } + // Make sure that the profile path exists and it's a directory. bool exists; rv = lf->Exists(&exists); @@ -2077,3 +2086,47 @@ nsresult XRE_GetFileFromPath(const char* aPath, nsIFile** aResult) { # error Platform-specific logic needed here. #endif } + +// Check for write permission to the profile directory by trying to create a +// new file (after ensuring that no file with the same name exists). +ProfileStatus nsToolkitProfileService::CheckProfileWriteAccess( + nsIFile* aProfileDir) { +#if defined(XP_UNIX) + constexpr auto writeTestFileName = u".parentwritetest"_ns; +#else + constexpr auto writeTestFileName = u"parent.writetest"_ns; +#endif + + nsCOMPtr<nsIFile> writeTestFile; + nsresult rv = aProfileDir->Clone(getter_AddRefs(writeTestFile)); + if (NS_SUCCEEDED(rv)) rv = writeTestFile->Append(writeTestFileName); + + if (NS_SUCCEEDED(rv)) { + bool doesExist = false; + rv = writeTestFile->Exists(&doesExist); + if (NS_SUCCEEDED(rv) && doesExist) rv = writeTestFile->Remove(true); + } + + if (NS_SUCCEEDED(rv)) { + rv = writeTestFile->Create(nsIFile::NORMAL_FILE_TYPE, 0666); + (void)writeTestFile->Remove(true); + } + + ProfileStatus status = + NS_SUCCEEDED(rv) ? PROFILE_STATUS_OK : PROFILE_STATUS_OTHER_ERROR; + if (NS_ERROR_FILE_ACCESS_DENIED == rv) + status = PROFILE_STATUS_ACCESS_DENIED; + else if (NS_ERROR_FILE_READ_ONLY == rv) + status = PROFILE_STATUS_READ_ONLY; + + return status; +} + +ProfileStatus nsToolkitProfileService::CheckProfileWriteAccess( + nsIToolkitProfile* aProfile) { + nsCOMPtr<nsIFile> profileDir; + nsresult rv = aProfile->GetRootDir(getter_AddRefs(profileDir)); + if (NS_FAILED(rv)) return PROFILE_STATUS_OTHER_ERROR; + + return CheckProfileWriteAccess(profileDir); +} diff --git a/toolkit/profile/nsToolkitProfileService.h b/toolkit/profile/nsToolkitProfileService.h index f2a238312b95..cfb1964ee1d7 100644 --- a/toolkit/profile/nsToolkitProfileService.h +++ b/toolkit/profile/nsToolkitProfileService.h @@ -15,6 +15,14 @@ #include "nsProfileLock.h" #include "nsINIParser.h" +enum ProfileStatus { + PROFILE_STATUS_OK, + PROFILE_STATUS_ACCESS_DENIED, + PROFILE_STATUS_READ_ONLY, + PROFILE_STATUS_IS_LOCKED, + PROFILE_STATUS_OTHER_ERROR +}; + class nsToolkitProfile final : public nsIToolkitProfile, public mozilla::LinkedListElement<RefPtr<nsToolkitProfile>> { @@ -79,10 +87,13 @@ class nsToolkitProfileService final : public nsIToolkitProfileService { nsresult SelectStartupProfile(int* aArgc, char* aArgv[], bool aIsResetting, nsIFile** aRootDir, nsIFile** aLocalDir, nsIToolkitProfile** aProfile, bool* aDidCreate, - bool* aWasDefaultSelection); + bool* aWasDefaultSelection, + ProfileStatus& aProfileStatus); nsresult CreateResetProfile(nsIToolkitProfile** aNewProfile); nsresult ApplyResetProfile(nsIToolkitProfile* aOldProfile); void CompleteStartup(); + static ProfileStatus CheckProfileWriteAccess(nsIToolkitProfile* aProfile); + static ProfileStatus CheckProfileWriteAccess(nsIFile* aProfileDir); private: friend class nsToolkitProfile; diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 1f7003ccf83c..21c5415a5dff 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -2214,6 +2214,91 @@ nsresult LaunchChild(bool aBlankCommandLine) { return NS_ERROR_LAUNCHED_CHILD_PROCESS; } +static nsresult GetOverrideStringBundleForLocale(nsIStringBundleService* aSBS, + const char* aTorbuttonURI, + const char* aLocale, + nsIStringBundle** aResult) { + NS_ENSURE_ARG(aSBS); + NS_ENSURE_ARG(aTorbuttonURI); + NS_ENSURE_ARG(aLocale); + NS_ENSURE_ARG(aResult); + + const char* kFormatStr = + "jar:%s!/chrome/torbutton/locale/%s/torbutton.properties"; + nsPrintfCString strBundleURL(kFormatStr, aTorbuttonURI, aLocale); + nsresult rv = aSBS->CreateBundle(strBundleURL.get(), aResult); + NS_ENSURE_SUCCESS(rv, rv); + + // To ensure that we have a valid string bundle, try to retrieve a string + // that we know exists. + nsAutoString val; + rv = (*aResult)->GetStringFromName("profileProblemTitle", val); + if (!NS_SUCCEEDED(rv)) *aResult = nullptr; // No good. Discard it. + + return rv; +} + +static void GetOverrideStringBundle(nsIStringBundleService* aSBS, + nsIStringBundle** aResult) { + if (!aSBS || !aResult) return; + + *aResult = nullptr; + + // Build Torbutton file URI string by starting from GREDir. + RefPtr<nsXREDirProvider> dirProvider = nsXREDirProvider::GetSingleton(); + if (!dirProvider) return; + + nsCOMPtr<nsIFile> greDir = dirProvider->GetGREDir(); + if (!greDir) return; + + // Create file URI, extract as string, and append omni.ja relative path. + nsCOMPtr<nsIURI> uri; + nsAutoCString uriString; + if (NS_FAILED(NS_NewFileURI(getter_AddRefs(uri), greDir)) || + NS_FAILED(uri->GetSpec(uriString))) { + return; + } + + uriString.Append("omni.ja"); + + nsAutoCString userAgentLocale; + if (!NS_SUCCEEDED( + Preferences::GetCString("intl.locale.requested", userAgentLocale))) { + return; + } + + nsresult rv = GetOverrideStringBundleForLocale( + aSBS, uriString.get(), userAgentLocale.get(), aResult); + if (NS_FAILED(rv)) { + // Try again using base locale, e.g., "en" vs. "en-US". + int16_t offset = userAgentLocale.FindChar('-', 1); + if (offset > 0) { + nsAutoCString shortLocale(Substring(userAgentLocale, 0, offset)); + rv = GetOverrideStringBundleForLocale(aSBS, uriString.get(), + shortLocale.get(), aResult); + } + } +} + +static nsresult GetFormattedString(nsIStringBundle* aOverrideBundle, + nsIStringBundle* aMainBundle, + const char* aName, + const nsTArray<nsString>& aParams, + nsAString& aResult) { + NS_ENSURE_ARG(aName); + + nsresult rv = NS_ERROR_FAILURE; + if (aOverrideBundle) { + rv = aOverrideBundle->FormatStringFromName(aName, aParams, aResult); + } + + // If string was not found in override bundle, use main (browser) bundle. + if (NS_FAILED(rv) && aMainBundle) + rv = aMainBundle->FormatStringFromName(aName, aParams, aResult); + + return rv; +} + static const char kProfileProperties[] = "chrome://mozapps/locale/profile/profileSelection.properties"; @@ -2262,7 +2347,7 @@ static nsresult ProfileMissingDialog(nsINativeAppSupport* aNative) { sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb)); NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE); - NS_ConvertUTF8toUTF16 appName(gAppData->name); + NS_ConvertUTF8toUTF16 appName(MOZ_APP_DISPLAYNAME); AutoTArray<nsString, 2> params = {appName, appName}; // profileMissing @@ -2284,11 +2369,12 @@ static nsresult ProfileMissingDialog(nsINativeAppSupport* aNative) { } } -static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir, - nsIFile* aProfileLocalDir, - nsIProfileUnlocker* aUnlocker, - nsINativeAppSupport* aNative, - nsIProfileLock** aResult) { +static ReturnAbortOnError ProfileErrorDialog(nsIFile* aProfileDir, + nsIFile* aProfileLocalDir, + ProfileStatus aStatus, + nsIProfileUnlocker* aUnlocker, + nsINativeAppSupport* aNative, + nsIProfileLock** aResult) { nsresult rv; bool exists; @@ -2316,24 +2402,39 @@ static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir, sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb)); NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE); - NS_ConvertUTF8toUTF16 appName(gAppData->name); + nsCOMPtr<nsIStringBundle> overrideSB; + GetOverrideStringBundle(sbs, getter_AddRefs(overrideSB)); + + NS_ConvertUTF8toUTF16 appName(MOZ_APP_DISPLAYNAME); AutoTArray<nsString, 3> params = {appName, appName, appName}; nsAutoString killMessage; #ifndef XP_MACOSX - rv = sb->FormatStringFromName( - aUnlocker ? "restartMessageUnlocker" : "restartMessageNoUnlocker2", - params, killMessage); + static const char kRestartUnlocker[] = "restartMessageUnlocker"; + static const char kRestartNoUnlocker[] = "restartMessageNoUnlocker2"; + static const char kReadOnly[] = "profileReadOnly"; #else - rv = sb->FormatStringFromName( - aUnlocker ? "restartMessageUnlockerMac" : "restartMessageNoUnlockerMac", - params, killMessage); -#endif + static const char kRestartUnlocker[] = "restartMessageUnlockerMac"; + static const char kRestartNoUnlocker[] = "restartMessageNoUnlockerMac"; + static const char kReadOnly[] = "profileReadOnlyMac"; +#endif + static const char kAccessDenied[] = "profileAccessDenied"; + + const char* errorKey = aUnlocker ? kRestartUnlocker : kRestartNoUnlocker; + if (PROFILE_STATUS_READ_ONLY == aStatus) + errorKey = kReadOnly; + else if (PROFILE_STATUS_ACCESS_DENIED == aStatus) + errorKey = kAccessDenied; + rv = GetFormattedString(overrideSB, sb, errorKey, params, killMessage); NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); + const char* titleKey = ((PROFILE_STATUS_READ_ONLY == aStatus) || + (PROFILE_STATUS_ACCESS_DENIED == aStatus)) + ? "profileProblemTitle" + : "restartTitle"; params.SetLength(1); nsAutoString killTitle; - rv = sb->FormatStringFromName("restartTitle", params, killTitle); + rv = sb->FormatStringFromName(titleKey, params, killTitle); NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); if (gfxPlatform::IsHeadless()) { @@ -2492,6 +2593,13 @@ static nsCOMPtr<nsIToolkitProfile> gResetOldProfile; static nsresult LockProfile(nsINativeAppSupport* aNative, nsIFile* aRootDir, nsIFile* aLocalDir, nsIToolkitProfile* aProfile, nsIProfileLock** aResult) { + ProfileStatus status = + (aProfile ? nsToolkitProfileService::CheckProfileWriteAccess(aProfile) + : nsToolkitProfileService::CheckProfileWriteAccess(aRootDir)); + if (PROFILE_STATUS_OK != status) + return ProfileErrorDialog(aRootDir, aLocalDir, status, nullptr, aNative, + aResult); + // If you close Firefox and very quickly reopen it, the old Firefox may // still be closing down. Rather than immediately showing the // "Firefox is running but is not responding" message, we spend a few @@ -2518,7 +2626,8 @@ static nsresult LockProfile(nsINativeAppSupport* aNative, nsIFile* aRootDir, } while (TimeStamp::Now() - start < TimeDuration::FromSeconds(kLockRetrySeconds)); - return ProfileLockedDialog(aRootDir, aLocalDir, unlocker, aNative, aResult); + return ProfileErrorDialog(aRootDir, aLocalDir, PROFILE_STATUS_IS_LOCKED, + unlocker, aNative, aResult); } // Pick a profile. We need to end up with a profile root dir, local dir and @@ -2533,7 +2642,8 @@ static nsresult LockProfile(nsINativeAppSupport* aNative, nsIFile* aRootDir, static nsresult SelectProfile(nsToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative, nsIFile** aRootDir, nsIFile** aLocalDir, nsIToolkitProfile** aProfile, - bool* aWasDefaultSelection) { + bool* aWasDefaultSelection, + nsIProfileLock** aResult) { StartupTimeline::Record(StartupTimeline::SELECT_PROFILE); nsresult rv; @@ -2579,9 +2689,14 @@ static nsresult SelectProfile(nsToolkitProfileService* aProfileSvc, // Ask the profile manager to select the profile directories to use. bool didCreate = false; - rv = aProfileSvc->SelectStartupProfile(&gArgc, gArgv, gDoProfileReset, - aRootDir, aLocalDir, aProfile, - &didCreate, aWasDefaultSelection); + ProfileStatus profileStatus = PROFILE_STATUS_OK; + rv = aProfileSvc->SelectStartupProfile( + &gArgc, gArgv, gDoProfileReset, aRootDir, aLocalDir, aProfile, &didCreate, + aWasDefaultSelection, profileStatus); + if (PROFILE_STATUS_OK != profileStatus) { + return ProfileErrorDialog(*aRootDir, *aLocalDir, profileStatus, nullptr, + aNative, aResult); + } if (rv == NS_ERROR_SHOW_PROFILE_MANAGER) { return ShowProfileManager(aProfileSvc, aNative); @@ -4359,7 +4474,7 @@ int XREMain::XRE_mainStartup(bool* aExitFlag) { nsCOMPtr<nsIToolkitProfile> profile; rv = SelectProfile(mProfileSvc, mNativeApp, getter_AddRefs(mProfD), getter_AddRefs(mProfLD), getter_AddRefs(profile), - &wasDefaultSelection); + &wasDefaultSelection, getter_AddRefs(mProfileLock)); if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) { *aExitFlag = true; return 0;
1 0
0 0
[tor-browser/tor-browser-84.0-10.5-1] Bug 9173: Change the default Firefox profile directory to be TBB-relative.
by sysrqb@torproject.org 09 Dec '20

09 Dec '20
commit b618e2c1d89cb8507546150dcd750dbc2022f83b Author: Kathy Brade <brade(a)pearlcrescent.com> Date: Fri Oct 18 15:20:06 2013 -0400 Bug 9173: Change the default Firefox profile directory to be TBB-relative. This should eliminate our need to rely on a wrapper script that sets /Users/arthur and launches Firefox with -profile. --- toolkit/profile/nsToolkitProfileService.cpp | 5 +- toolkit/xre/nsAppRunner.cpp | 2 +- toolkit/xre/nsConsoleWriter.cpp | 2 +- toolkit/xre/nsXREDirProvider.cpp | 149 ++++++---------------------- toolkit/xre/nsXREDirProvider.h | 16 +-- xpcom/io/nsAppFileLocationProvider.cpp | 97 +++++++----------- 6 files changed, 84 insertions(+), 187 deletions(-) diff --git a/toolkit/profile/nsToolkitProfileService.cpp b/toolkit/profile/nsToolkitProfileService.cpp index 4af61d54d19b..060248c42689 100644 --- a/toolkit/profile/nsToolkitProfileService.cpp +++ b/toolkit/profile/nsToolkitProfileService.cpp @@ -723,10 +723,11 @@ nsresult nsToolkitProfileService::Init() { NS_ASSERTION(gDirServiceProvider, "No dirserviceprovider!"); nsresult rv; - rv = nsXREDirProvider::GetUserAppDataDirectory(getter_AddRefs(mAppData)); + rv = gDirServiceProvider->GetUserAppDataDirectory(getter_AddRefs(mAppData)); NS_ENSURE_SUCCESS(rv, rv); - rv = nsXREDirProvider::GetUserLocalDataDirectory(getter_AddRefs(mTempData)); + rv = + gDirServiceProvider->GetUserLocalDataDirectory(getter_AddRefs(mTempData)); NS_ENSURE_SUCCESS(rv, rv); rv = mAppData->Clone(getter_AddRefs(mProfileDBFile)); diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 40e4dae574dc..1f7003ccf83c 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -3614,7 +3614,7 @@ int XREMain::XRE_mainInit(bool* aExitFlag) { if ((mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER) && NS_SUCCEEDED(CrashReporter::SetExceptionHandler(xreBinDirectory))) { nsCOMPtr<nsIFile> file; - rv = nsXREDirProvider::GetUserAppDataDirectory(getter_AddRefs(file)); + rv = mDirProvider.GetUserAppDataDirectory(getter_AddRefs(file)); if (NS_SUCCEEDED(rv)) { CrashReporter::SetUserAppDataDirectory(file); } diff --git a/toolkit/xre/nsConsoleWriter.cpp b/toolkit/xre/nsConsoleWriter.cpp index d89ea3bde31d..4a9a6d28034a 100644 --- a/toolkit/xre/nsConsoleWriter.cpp +++ b/toolkit/xre/nsConsoleWriter.cpp @@ -29,7 +29,7 @@ void WriteConsoleLog() { } else { if (!gLogConsoleErrors) return; - rv = nsXREDirProvider::GetUserAppDataDirectory(getter_AddRefs(lfile)); + rv = gDirServiceProvider->GetUserAppDataDirectory(getter_AddRefs(lfile)); if (NS_FAILED(rv)) return; lfile->AppendNative("console.log"_ns); diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp index 2760be996403..b88fd3eb368c 100644 --- a/toolkit/xre/nsXREDirProvider.cpp +++ b/toolkit/xre/nsXREDirProvider.cpp @@ -32,6 +32,7 @@ #include "nsArrayEnumerator.h" #include "nsEnumeratorUtils.h" #include "nsReadableUtils.h" +#include "nsXPCOMPrivate.h" // for XPCOM_FILE_PATH_SEPARATOR #include "SpecialSystemDirectory.h" @@ -244,9 +245,6 @@ nsresult nsXREDirProvider::GetUserProfilesRootDir(nsIFile** aResult) { nsresult rv = GetUserDataDirectory(getter_AddRefs(file), false); if (NS_SUCCEEDED(rv)) { -#if !defined(XP_UNIX) || defined(XP_MACOSX) - rv = file->AppendNative("Profiles"_ns); -#endif // We must create the profile directory here if it does not exist. nsresult tmp = EnsureDirectoryExists(file); if (NS_FAILED(tmp)) { @@ -262,9 +260,6 @@ nsresult nsXREDirProvider::GetUserProfilesLocalDir(nsIFile** aResult) { nsresult rv = GetUserDataDirectory(getter_AddRefs(file), true); if (NS_SUCCEEDED(rv)) { -#if !defined(XP_UNIX) || defined(XP_MACOSX) - rv = file->AppendNative("Profiles"_ns); -#endif // We must create the profile directory here if it does not exist. nsresult tmp = EnsureDirectoryExists(file); if (NS_FAILED(tmp)) { @@ -1394,7 +1389,7 @@ nsresult nsXREDirProvider::SetUserDataProfileDirectory(nsCOMPtr<nsIFile>& aFile, nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal) { // Copied from nsAppFileLocationProvider (more or less) - nsresult rv; + NS_ENSURE_ARG_POINTER(aFile); nsCOMPtr<nsIFile> localDir; if (aLocal && gDataDirHomeLocal) { @@ -1404,80 +1399,39 @@ nsresult nsXREDirProvider::GetUserDataDirectoryHome(nsIFile** aFile, return gDataDirHome->Clone(aFile); } -#if defined(XP_MACOSX) - FSRef fsRef; - OSType folderType; - if (aLocal) { - folderType = kCachedDataFolderType; - } else { -# ifdef MOZ_THUNDERBIRD - folderType = kDomainLibraryFolderType; -# else - folderType = kApplicationSupportFolderType; -# endif - } - OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef); - NS_ENSURE_FALSE(err, NS_ERROR_FAILURE); - - rv = NS_NewNativeLocalFile(""_ns, true, getter_AddRefs(localDir)); + nsresult rv = GetAppDir()->Clone(getter_AddRefs(localDir)); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr<nsILocalFileMac> dirFileMac = do_QueryInterface(localDir); - NS_ENSURE_TRUE(dirFileMac, NS_ERROR_UNEXPECTED); - - rv = dirFileMac->InitWithFSRef(&fsRef); - 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("."); - localDir = dirFileMac; -#elif defined(XP_IOS) - nsAutoCString userDir; - if (GetUIKitDirectory(aLocal, userDir)) { - rv = NS_NewNativeLocalFile(userDir, true, getter_AddRefs(localDir)); - } else { - rv = NS_ERROR_FAILURE; - } - NS_ENSURE_SUCCESS(rv, rv); -#elif defined(XP_WIN) - nsString path; - if (aLocal) { - rv = GetShellFolderPath(FOLDERID_LocalAppData, path); - if (NS_FAILED(rv)) rv = GetRegWindowsAppDataFolder(aLocal, path); - } - if (!aLocal || NS_FAILED(rv)) { - rv = GetShellFolderPath(FOLDERID_RoamingAppData, path); - if (NS_FAILED(rv)) { - if (!aLocal) rv = GetRegWindowsAppDataFolder(aLocal, path); - } + // Remove a directory component. + nsCOMPtr<nsIFile> parentDir; + rv = localDir->GetParent(getter_AddRefs(parentDir)); + NS_ENSURE_SUCCESS(rv, rv); + localDir = parentDir; + if (didRemove) --levelsToRemove; } - NS_ENSURE_SUCCESS(rv, rv); - rv = NS_NewLocalFile(path, true, getter_AddRefs(localDir)); -#elif defined(XP_UNIX) - const char* homeDir = getenv("HOME"); - if (!homeDir || !*homeDir) return NS_ERROR_FAILURE; + if (!localDir) return NS_ERROR_FAILURE; -# ifdef ANDROID /* We want (ProfD == ProfLD) on Android. */ - aLocal = false; -# endif + rv = localDir->AppendRelativeNativePath("TorBrowser" XPCOM_FILE_PATH_SEPARATOR + "Data" XPCOM_FILE_PATH_SEPARATOR + "Browser"_ns); + NS_ENSURE_SUCCESS(rv, rv); if (aLocal) { - // If $XDG_CACHE_HOME is defined use it, otherwise use $HOME/.cache. - const char* cacheHome = getenv("XDG_CACHE_HOME"); - if (cacheHome && *cacheHome) { - rv = NS_NewNativeLocalFile(nsDependentCString(cacheHome), true, - getter_AddRefs(localDir)); - } else { - rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true, - getter_AddRefs(localDir)); - if (NS_SUCCEEDED(rv)) rv = localDir->AppendNative(".cache"_ns); - } - } else { - rv = NS_NewNativeLocalFile(nsDependentCString(homeDir), true, - getter_AddRefs(localDir)); + rv = localDir->AppendNative("Caches"_ns); + NS_ENSURE_SUCCESS(rv, rv); } -#else -# error "Don't know how to get product dir on your platform" -#endif NS_IF_ADDREF(*aFile = localDir); return rv; @@ -1660,39 +1614,23 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) { } nsAutoCString profile; - nsAutoCString appName; - nsAutoCString vendor; if (gAppData->profile) { profile = gAppData->profile; - } else { - appName = gAppData->name; - vendor = gAppData->vendor; } - nsresult rv = NS_OK; + nsresult rv = NS_ERROR_FAILURE; #if defined(XP_MACOSX) if (!profile.IsEmpty()) { rv = AppendProfileString(aFile, profile.get()); - } else { - // Note that MacOS ignores the vendor when creating the profile hierarchy - - // all application preferences directories live alongside one another in - // ~/Library/Application Support/ - rv = aFile->AppendNative(appName); + NS_ENSURE_SUCCESS(rv, rv); } - NS_ENSURE_SUCCESS(rv, rv); #elif defined(XP_WIN) if (!profile.IsEmpty()) { rv = AppendProfileString(aFile, profile.get()); - } else { - if (!vendor.IsEmpty()) { - rv = aFile->AppendNative(vendor); - NS_ENSURE_SUCCESS(rv, rv); - } - rv = aFile->AppendNative(appName); + NS_ENSURE_SUCCESS(rv, rv); } - NS_ENSURE_SUCCESS(rv, rv); #elif defined(ANDROID) // The directory used for storing profiles @@ -1702,11 +1640,6 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) { rv = aFile->AppendNative(nsDependentCString("mozilla")); NS_ENSURE_SUCCESS(rv, rv); #elif defined(XP_UNIX) - nsAutoCString folder; - // Make it hidden (by starting with "."), except when local (the - // profile is already under ~/.cache or XDG_CACHE_HOME). - if (!aLocal) folder.Assign('.'); - if (!profile.IsEmpty()) { // Skip any leading path characters const char* profileStart = profile.get(); @@ -1714,32 +1647,16 @@ nsresult nsXREDirProvider::AppendProfilePath(nsIFile* aFile, bool aLocal) { // On the off chance that someone wanted their folder to be hidden don't // let it become ".." - if (*profileStart == '.' && !aLocal) profileStart++; + if (*profileStart == '.') profileStart++; + // Make it hidden (by starting with "."). + nsAutoCString folder("."); folder.Append(profileStart); ToLowerCase(folder); rv = AppendProfileString(aFile, folder.BeginReading()); - } else { - if (!vendor.IsEmpty()) { - folder.Append(vendor); - ToLowerCase(folder); - - rv = aFile->AppendNative(folder); - NS_ENSURE_SUCCESS(rv, rv); - - folder.Truncate(); - } - - // This can be the case in tests. - if (!appName.IsEmpty()) { - folder.Append(appName); - ToLowerCase(folder); - - rv = aFile->AppendNative(folder); - } + NS_ENSURE_SUCCESS(rv, rv); } - NS_ENSURE_SUCCESS(rv, rv); #else # error "Don't know how to get profile path on your platform" diff --git a/toolkit/xre/nsXREDirProvider.h b/toolkit/xre/nsXREDirProvider.h index e55b4e153c56..b9678d4ec577 100644 --- a/toolkit/xre/nsXREDirProvider.h +++ b/toolkit/xre/nsXREDirProvider.h @@ -63,15 +63,19 @@ class nsXREDirProvider final : public nsIDirectoryServiceProvider2, void DoShutdown(); - static nsresult GetUserAppDataDirectory(nsIFile** aFile) { + nsresult GetUserAppDataDirectory(nsIFile** aFile) { return GetUserDataDirectory(aFile, false); } - static nsresult GetUserLocalDataDirectory(nsIFile** aFile) { + nsresult GetUserLocalDataDirectory(nsIFile** aFile) { return GetUserDataDirectory(aFile, true); } // GetUserDataDirectory gets the profile path from gAppData. - static nsresult GetUserDataDirectory(nsIFile** aFile, bool aLocal); + + // This function now calls GetAppDir(), so it cannot be static anymore. + // The same happens with all the functions (in)directly calling this one (the + // rest of Get*Directory functions in this file) + nsresult GetUserDataDirectory(nsIFile** aFile, bool aLocal); /* make sure you clone it, if you need to do stuff to it */ nsIFile* GetGREDir() { return mGREDir; } @@ -112,9 +116,9 @@ class nsXREDirProvider final : public nsIDirectoryServiceProvider2, protected: nsresult GetFilesInternal(const char* aProperty, nsISimpleEnumerator** aResult); - static nsresult GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal); - static nsresult GetSysUserExtensionsDirectory(nsIFile** aFile); - static nsresult GetSysUserExtensionsDevDirectory(nsIFile** aFile); + nsresult GetUserDataDirectoryHome(nsIFile** aFile, bool aLocal); + nsresult GetSysUserExtensionsDirectory(nsIFile** aFile); + nsresult GetSysUserExtensionsDevDirectory(nsIFile** aFile); #if defined(XP_UNIX) || defined(XP_MACOSX) static nsresult GetSystemExtensionsDirectory(nsIFile** aFile); #endif diff --git a/xpcom/io/nsAppFileLocationProvider.cpp b/xpcom/io/nsAppFileLocationProvider.cpp index ef974f99048f..2bbcee92aedb 100644 --- a/xpcom/io/nsAppFileLocationProvider.cpp +++ b/xpcom/io/nsAppFileLocationProvider.cpp @@ -15,6 +15,7 @@ #include "nsSimpleEnumerator.h" #include "prenv.h" #include "nsCRT.h" +#include "nsXPCOMPrivate.h" // for XPCOM_FILE_PATH_SEPARATOR #if defined(MOZ_WIDGET_COCOA) # include <Carbon/Carbon.h> # include "nsILocalFileMac.h" @@ -233,9 +234,8 @@ nsresult nsAppFileLocationProvider::CloneMozBinDirectory(nsIFile** aLocalFile) { // GetProductDirectory - Gets the directory which contains the application data // folder // -// UNIX : ~/.mozilla/ -// WIN : <Application Data folder on user's machine>\Mozilla -// Mac : :Documents:Mozilla: +// UNIX and WIN : <App Folder>/TorBrowser/Data/Browser +// Mac : <App Folder>/../../TorBrowser/Data/Browser //---------------------------------------------------------------------------------------- nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile, bool aLocal) { @@ -247,49 +247,45 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile, bool exists; nsCOMPtr<nsIFile> localDir; -#if defined(MOZ_WIDGET_COCOA) - FSRef fsRef; - OSType folderType = - aLocal ? (OSType)kCachedDataFolderType : (OSType)kDomainLibraryFolderType; - OSErr err = ::FSFindFolder(kUserDomain, folderType, kCreateFolder, &fsRef); - if (err) { - return NS_ERROR_FAILURE; + rv = CloneMozBinDirectory(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; + } } - NS_NewLocalFile(u""_ns, true, getter_AddRefs(localDir)); + if (!localDir) { return NS_ERROR_FAILURE; } - nsCOMPtr<nsILocalFileMac> localDirMac(do_QueryInterface(localDir)); - rv = localDirMac->InitWithFSRef(&fsRef); - if (NS_FAILED(rv)) { - return rv; - } -#elif defined(XP_WIN) - nsCOMPtr<nsIProperties> directoryService = - do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) { - return rv; - } - const char* prop = aLocal ? NS_WIN_LOCAL_APPDATA_DIR : NS_WIN_APPDATA_DIR; - rv = directoryService->Get(prop, NS_GET_IID(nsIFile), - getter_AddRefs(localDir)); - if (NS_FAILED(rv)) { - return rv; - } -#elif defined(XP_UNIX) - rv = NS_NewNativeLocalFile(nsDependentCString(PR_GetEnv("HOME")), true, - getter_AddRefs(localDir)); - if (NS_FAILED(rv)) { - return rv; - } -#else -# error dont_know_how_to_get_product_dir_on_your_platform -#endif - rv = localDir->AppendRelativeNativePath(DEFAULT_PRODUCT_DIR); - if (NS_FAILED(rv)) { - return rv; + rv = localDir->AppendRelativeNativePath("TorBrowser" XPCOM_FILE_PATH_SEPARATOR + "Data" XPCOM_FILE_PATH_SEPARATOR + "Browser"_ns); + NS_ENSURE_SUCCESS(rv, rv); + + if (aLocal) { + rv = localDir->AppendNative("Caches"_ns); + NS_ENSURE_SUCCESS(rv, rv); } + rv = localDir->Exists(&exists); if (NS_SUCCEEDED(rv) && !exists) { @@ -308,10 +304,6 @@ nsresult nsAppFileLocationProvider::GetProductDirectory(nsIFile** aLocalFile, //---------------------------------------------------------------------------------------- // GetDefaultUserProfileRoot - Gets the directory which contains each user // profile dir -// -// UNIX : ~/.mozilla/ -// WIN : <Application Data folder on user's machine>\Mozilla\Profiles -// Mac : :Documents:Mozilla:Profiles: //---------------------------------------------------------------------------------------- nsresult nsAppFileLocationProvider::GetDefaultUserProfileRoot( nsIFile** aLocalFile, bool aLocal) { @@ -327,23 +319,6 @@ nsresult nsAppFileLocationProvider::GetDefaultUserProfileRoot( return rv; } -#if defined(MOZ_WIDGET_COCOA) || defined(XP_WIN) - // These 3 platforms share this part of the path - do them as one - rv = localDir->AppendRelativeNativePath("Profiles"_ns); - if (NS_FAILED(rv)) { - return rv; - } - - bool exists; - rv = localDir->Exists(&exists); - if (NS_SUCCEEDED(rv) && !exists) { - rv = localDir->Create(nsIFile::DIRECTORY_TYPE, 0775); - } - if (NS_FAILED(rv)) { - return rv; - } -#endif - localDir.forget(aLocalFile); return rv;
1 0
0 0
[tor-browser/tor-browser-84.0-10.5-1] Bug 16620: Clear window.name when no referrer sent
by sysrqb@torproject.org 09 Dec '20

09 Dec '20
commit e290ebf5e0935e4cf9aa8c65382280f3f7fbf732 Author: Kathy Brade <brade(a)pearlcrescent.com> Date: Fri Oct 30 14:28:13 2015 -0400 Bug 16620: Clear window.name when no referrer sent Convert JS implementation (within Torbutton) to a C++ browser patch. --- docshell/base/nsDocShell.cpp | 60 +++++++ docshell/test/mochitest/mochitest.ini | 3 + docshell/test/mochitest/test_tor_bug16620.html | 212 +++++++++++++++++++++++++ docshell/test/mochitest/tor_bug16620.html | 51 ++++++ docshell/test/mochitest/tor_bug16620_form.html | 51 ++++++ 5 files changed, 377 insertions(+) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index c924653a10ef..b440da6b5ffe 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -7742,11 +7742,71 @@ nsresult nsDocShell::CreateContentViewer(const nsACString& aContentType, aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI)); } FirePageHideNotification(!mSavingOldViewer); + if (mIsBeingDestroyed) { // Force to stop the newly created orphaned viewer. viewer->Stop(); return NS_ERROR_DOCSHELL_DYING; } + + // Tor bug 16620: Clear window.name of top-level documents if + // there is no referrer. We make an exception for new windows, + // e.g., window.open(url, "MyName"). + bool isNewWindowTarget = false; + nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aRequest, &rv)); + if (props) { + props->GetPropertyAsBool(u"docshell.newWindowTarget"_ns, + &isNewWindowTarget); + } + + if (!isNewWindowTarget) { + nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aOpenedChannel)); + nsCOMPtr<nsIURI> httpReferrer; + if (httpChannel) { + nsCOMPtr<nsIReferrerInfo> referrerInfo; + rv = httpChannel->GetReferrerInfo(getter_AddRefs(referrerInfo)); + NS_ENSURE_SUCCESS(rv, rv); + if (referrerInfo) { + // We want GetComputedReferrer() instead of GetOriginalReferrer(), since + // the former takes into consideration referrer policy, protocol + // whitelisting... + httpReferrer = referrerInfo->GetComputedReferrer(); + } + } + + bool isTopFrame = mBrowsingContext->IsTop(); + +#ifdef DEBUG_WINDOW_NAME + printf("DOCSHELL %p CreateContentViewer - possibly clearing window.name:\n", + this); + printf(" current window.name: \"%s\"\n", + NS_ConvertUTF16toUTF8(mName).get()); + + nsAutoCString curSpec, loadingSpec; + if (this->mCurrentURI) mCurrentURI->GetSpec(curSpec); + if (mLoadingURI) mLoadingURI->GetSpec(loadingSpec); + printf(" current URI: %s\n", curSpec.get()); + printf(" loading URI: %s\n", loadingSpec.get()); + printf(" is top document: %s\n", isTopFrame ? "Yes" : "No"); + + if (!httpReferrer) { + printf(" referrer: None\n"); + } else { + nsAutoCString refSpec; + httpReferrer->GetSpec(refSpec); + printf(" referrer: %s\n", refSpec.get()); + } +#endif + + bool clearName = isTopFrame && !httpReferrer; + if (clearName) SetName(u""_ns); + +#ifdef DEBUG_WINDOW_NAME + printf(" action taken: %s window.name\n", + clearName ? "Cleared" : "Preserved"); +#endif + } + mLoadingURI = nullptr; // Set mFiredUnloadEvent = false so that the unload handler for the diff --git a/docshell/test/mochitest/mochitest.ini b/docshell/test/mochitest/mochitest.ini index b712654703f9..89b6718811c4 100644 --- a/docshell/test/mochitest/mochitest.ini +++ b/docshell/test/mochitest/mochitest.ini @@ -53,6 +53,8 @@ support-files = start_historyframe.html url1_historyframe.html url2_historyframe.html + tor_bug16620.html + tor_bug16620_form.html [test_anchor_scroll_after_document_open.html] [test_bfcache_plus_hash.html] @@ -127,6 +129,7 @@ support-files = file_history_length_during_pageload.html file_history_length_during_pageload_2.html [test_pushState_after_document_open.html] +[test_tor_bug16620.html] [test_navigate_after_pagehide.html] [test_redirect_history.html] support-files = diff --git a/docshell/test/mochitest/test_tor_bug16620.html b/docshell/test/mochitest/test_tor_bug16620.html new file mode 100644 index 000000000000..f60a06711c17 --- /dev/null +++ b/docshell/test/mochitest/test_tor_bug16620.html @@ -0,0 +1,212 @@ +<!DOCTYPE HTML> +<html> +<!-- + Tor Bug 16620: Clear window.name when no referrer sent. + https://trac.torproject.org/projects/tor/ticket/16620 +--> +<meta charset="utf-8"> +<head> + <title>Test for Tor Bug 16620 - Clear window.name when no referrer sent</title> + <script type="application/javascript" + src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://trac.torproject.org/projects/tor/ticket/16620">Tor Bug 16620</a> +<script type="application/javascript;version=1.7"> + +// ## Test constants +const kTestPath = "/tests/docshell/test/mochitest/"; +const kLinkFile = "tor_bug16620.html"; +const kFormFile = "tor_bug16620_form.html"; +const kBaseURL1 = "http://example.com"; +const kBaseURL1_https = "https://example.com"; +const kBaseURL2 = "http://example.net"; +const kSendReferrerPref = "network.http.sendRefererHeader"; +const kSendReferrerNever = 0; +const kSendReferrerForUserAction = 1; +const kSendReferrerAlways = 2; + +let gTests = [ + // Test #1: Same domain; never send referrer. + { startURL: kBaseURL1, destURL: kBaseURL1, + referrerPref: kSendReferrerNever, + expectIsolation: true }, + + // Test #2: Same domain; send referrer upon user action. + { startURL: kBaseURL1, destURL: kBaseURL1, + referrerPref: kSendReferrerForUserAction, + expectIsolation: false }, + + // Test #3: Same domain; always send referrer. + { startURL: kBaseURL1, destURL: kBaseURL1, + referrerPref: kSendReferrerAlways, + expectIsolation: false }, + + // Test #4: Different top-level domains; never send referrer. + { startURL: kBaseURL1, destURL: kBaseURL2, + referrerPref: kSendReferrerNever, + expectIsolation: true }, + + // Test #5: Different top-level domains; send referrer upon user action. + { startURL: kBaseURL1, destURL: kBaseURL2, + referrerPref: kSendReferrerForUserAction, + expectIsolation: false }, + + // Test #6: Different top-level domains; always send referrer. + { startURL: kBaseURL1, destURL: kBaseURL2, + referrerPref: kSendReferrerAlways, + expectIsolation: false }, + + // Test #7: https -> http transition. + { startURL: kBaseURL1_https, destURL: kBaseURL1, + referrerPref: kSendReferrerForUserAction, + expectIsolation: true }, + + // Test #8: Same domain, rel="noreferrer" on link. + { startURL: kBaseURL1, destURL: kBaseURL1, noReferrerOnLink: true, + referrerPref: kSendReferrerAlways, + expectIsolation: true }, + + // Test #9: Same domain, "no-referrer" meta tag in document. + { startURL: kBaseURL1, destURL: kBaseURL1, noReferrerInMetaTag: true, + referrerPref: kSendReferrerAlways, + expectIsolation: true }, + + // Test #10: Like test #9, but reset window.name during unload. + // (similar to http://www.thomasfrank.se/sessvarsTestPage1.html) + { startURL: kBaseURL1, destURL: kBaseURL1, noReferrerInMetaTag: true, + resetInUnload: true, + referrerPref: kSendReferrerAlways, + expectIsolation: true }, + + // Test #11: Data URL as destination (no referrer). + { startURL: kBaseURL1, + referrerPref: kSendReferrerAlways, + expectIsolation: true }, + + // Test #12: Ensure that window.name is preserved when a dynamically loaded + // iframe is used to perform a form post (regression test for Tor bug 18168). + { startURL: kBaseURL1, + isFormTest: true, + referrerPref: kSendReferrerAlways, + expectIsolation: false }, +]; + +let gCurTest = 0; +let gCurWinName, gChildWin, gDataURL; + +// ## Utility functions +function generateRandomName() +{ + // Generate a random 6 character string using 0-9 and a-z. + return ((1 + Math.random()).toString(36) + '000000').substr(2, 6); +} + +function startNextTest() { + ++gCurTest; + if (gCurTest > gTests.length) { + SimpleTest.finish(); + } else { + let curTest = gTests[gCurTest - 1]; + if ("referrerPref" in curTest) + SpecialPowers.setIntPref(kSendReferrerPref, curTest.referrerPref); + else + SpecialPowers.setIntPref(kSendReferrerPref, kSendReferrerForUserAction); + gCurWinName = generateRandomName(); + let url = curTest.startURL + kTestPath; + if (curTest.isFormTest === true) { + url += kFormFile + "?" + gCurWinName; + gChildWin = window.open(url, undefined); + } else { + url += kLinkFile + "?firstDocLoaded"; + gChildWin = window.open(url, gCurWinName); + } + } +} + +// ## Add a message event listener. +window.addEventListener("message", function(aEvent) { + if (aEvent.source !== gChildWin) + return; + +// console.log("parent received message:" + JSON.stringify(aEvent.data)); + + let proceedToNextTest = false; + let curTest = gTests[gCurTest - 1]; + let state = aEvent.data.state; + let winName = aEvent.data.winName; + if ("firstDocLoaded" == state) { + // Process response from step one of the link-based tests. + let step1Passed = (winName === gCurWinName); + if (!step1Passed) { + ok(step1Passed, "Test #" + gCurTest + + " - first document's name matches window.open parameter"); + proceedToNextTest = true; + } + + // Send an "openURL" message to the loaded document. + let url2 = (curTest.destURL) + ? curTest.destURL + kTestPath + kLinkFile + "?secondDocLoaded" + : gDataURL; + let noReferrerOnLink = (curTest.noReferrerOnLink === true); + let noReferrerInMetaTag = (curTest.noReferrerInMetaTag === true); + let resetInUnload = (curTest.resetInUnload === true); + aEvent.source.postMessage({ action: "openURL", url: url2, + noReferrerOnLink: noReferrerOnLink, + noReferrerInMetaTag: noReferrerInMetaTag, + resetInUnload: resetInUnload }, + aEvent.origin); + } else if ("secondDocLoaded" == state) { + // Process response from step two of the link-based tests. + if (curTest.expectIsolation) { + ok(winName === "", + "Test #" + gCurTest + " - second document: name was cleared"); + } else { + ok(winName === gCurWinName, + "Test #" + gCurTest + " - second document: name was preserved"); + } + proceedToNextTest = true; + } else if ("formPostDone" == state) { + // Process response from the form post tests. + if (curTest.expectIsolation) { + ok(winName === "", + "Test #" + gCurTest + " - iframe form post: name was cleared"); + } else { + ok(winName === gCurWinName, + "Test #" + gCurTest + " - iframe form post: name was preserved"); + } + proceedToNextTest = true; + + } + + if (proceedToNextTest) { + gChildWin.close(); + startNextTest(); + } + }, false); + + SimpleTest.waitForExplicitFinish(); + + if (SpecialPowers.getBoolPref("security.nocertdb")) { + // Mochitests don't simulate https correctly with "security.nocertdb" + // enabled. See https://bugs.torproject.org/18087 + ok(false, "Please disable the pref `security.nocertdb` before running this test."); + SimpleTest.finish(); + } else { + + // Read file contents, construct a data URL (used by some tests), and + // then start the first test. + let url = kTestPath + kLinkFile; + let xhr = new XMLHttpRequest(); + xhr.open("GET", url); + xhr.onload = function() { + gDataURL = "data:text/html;charset=utf-8," + + encodeURIComponent(this.responseText); + startNextTest(); + } + xhr.send(); + } +</script> +</body> +</html> diff --git a/docshell/test/mochitest/tor_bug16620.html b/docshell/test/mochitest/tor_bug16620.html new file mode 100644 index 000000000000..a8e90502f1d1 --- /dev/null +++ b/docshell/test/mochitest/tor_bug16620.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML> +<html> +<!-- + Tor Bug 16620: Clear window.name when no referrer sent. + https://trac.torproject.org/projects/tor/ticket/16620 +--> +<head> + <meta charset="UTF-8"> + <title>Supporting Doc for Tor Bug 16620 Tests</title> +</head> +<body> +<a id="link" href="">secondDoc</a> + +<script type="application/javascript;version=1.7"> +// Extract test state from our query string, defaulting to +// "secondDocLoaded" to support use of this HTML content within +// a data URI (where query strings are not supported). +let state = (location.search.length > 0) ? location.search.substr(1) + : "secondDocLoaded"; + +// Notify the test driver. +opener.postMessage({ state: state, winName: window.name }, "*"); + +// Add a message event listener to process "openURL" actions. +window.addEventListener("message", function(aEvent) { + if (aEvent.data.action == "openURL") { + if (aEvent.data.noReferrerInMetaTag) { + let metaElem = document.createElement("meta"); + metaElem.name = "referrer"; + metaElem.content = "no-referrer"; + document.head.appendChild(metaElem); + } + + let linkElem = document.getElementById("link"); + linkElem.href = aEvent.data.url; + if (aEvent.data.noReferrerOnLink) + linkElem.rel = "noreferrer"; + + if (aEvent.data.resetInUnload) { + let tmpName = window.name; + window.addEventListener("unload", function() { + window.name = tmpName; + }, false); + } + + linkElem.click(); + } +}, false); +</script> +</body> +</html> diff --git a/docshell/test/mochitest/tor_bug16620_form.html b/docshell/test/mochitest/tor_bug16620_form.html new file mode 100644 index 000000000000..3b6e6c72cfc9 --- /dev/null +++ b/docshell/test/mochitest/tor_bug16620_form.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML> +<html> +<!-- + Tor Bug 16620: Clear window.name when no referrer sent. + https://trac.torproject.org/projects/tor/ticket/16620 + + Regression test for bug 18168: iframe-based AJAX call opening in new tab +--> +<head> + <meta charset="UTF-8"> + <title>Supporting Form-based Doc for Tor Bug 16620 Tests</title> +</head> +<body> + +<script type="application/javascript;version=1.7"> +document.addEventListener("DOMContentLoaded", function () { + addPostTarget(); +}, false); + + +function addPostTarget() +{ + let frameName = location.search.substr(1); + let form = document.getElementById("postform"); + let iframe = document.createElement("iframe"); + iframe.style.border = "1px solid red"; + iframe.src = "about:blank"; + form.target = iframe.name = iframe.id = frameName; + document.body.appendChild(iframe); + + let didSubmit = false; + iframe.onload = function() { + if (!didSubmit) { + didSubmit = true; + let submitButton = document.getElementById("submitButton"); + submitButton.click(); + } else { + // Form submission complete. Report iframe's name to test driver. + opener.postMessage({ state: "formPostDone", winName: iframe.name }, "*"); + } + }; +} + +</script> +<form name="postform" id="postform" + action="data:text/plain;charset=utf-8,Hello%20world" + method="POST" enctype="multipart/form-data"> + <input type="hidden" name="field1" value="value1"><br> + <input id="submitButton" type="submit" value="Post It"> +</body> +</html>
1 0
0 0
[tor-browser/tor-browser-84.0-10.5-1] Bug 11641: change TBB directory structure to be more like Firefox's
by sysrqb@torproject.org 09 Dec '20

09 Dec '20
commit 210f80a39091a0078fcf661e75c3f662915a3c65 Author: Kathy Brade <brade(a)pearlcrescent.com> Date: Tue Apr 29 13:08:24 2014 -0400 Bug 11641: change TBB directory structure to be more like Firefox's Unless the -osint command line flag is used, the browser now defaults to the equivalent of -no-remote. There is a new -allow-remote flag that may be used to restore the original (Firefox-like) default behavior. --- toolkit/xre/nsAppRunner.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 51a1a43ec891..86f6d55988a9 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -1804,8 +1804,10 @@ static void DumpHelp() { " --migration Start with migration wizard.\n" " --ProfileManager Start with ProfileManager.\n" #ifdef MOZ_HAS_REMOTE - " --no-remote Do not accept or send remote commands; implies\n" + " --no-remote (default) Do not accept or send remote commands; " + "implies\n" " --new-instance.\n" + " --allow-remote Accept and send remote commands.\n" " --new-instance Open new instance, not a new window in running " "instance.\n" #endif @@ -3975,16 +3977,25 @@ int XREMain::XRE_mainInit(bool* aExitFlag) { gSafeMode); #if defined(MOZ_HAS_REMOTE) + // In Tor Browser, remoting is disabled by default unless -osint is used. + bool allowRemote = (CheckArg("allow-remote") == ARG_FOUND); + bool isOsint = (CheckArg("osint", nullptr, CheckArgFlag::None) == ARG_FOUND); + if (!allowRemote && !isOsint) { + SaveToEnv("MOZ_NO_REMOTE=1"); + } // Handle --no-remote and --new-instance command line arguments. Setup // the environment to better accommodate other components and various // restart scenarios. ar = CheckArg("no-remote"); - if (ar == ARG_FOUND || EnvHasValue("MOZ_NO_REMOTE")) { + if ((ar == ARG_FOUND) && allowRemote) { + PR_fprintf(PR_STDERR, + "Error: argument --no-remote is invalid when argument " + "--allow-remote is specified\n"); + return 1; + } + if (EnvHasValue("MOZ_NO_REMOTE")) { mDisableRemoteClient = true; mDisableRemoteServer = true; - if (!EnvHasValue("MOZ_NO_REMOTE")) { - SaveToEnv("MOZ_NO_REMOTE=1"); - } } ar = CheckArg("new-instance");
1 0
0 0
[tor-browser/tor-browser-84.0-10.5-1] Bug 18800: Remove localhost DNS lookup in nsProfileLock.cpp
by sysrqb@torproject.org 09 Dec '20

09 Dec '20
commit fa58df73558ab53d03d2730142656bd736879431 Author: Kathy Brade <brade(a)pearlcrescent.com> Date: Thu Apr 21 10:40:26 2016 -0400 Bug 18800: Remove localhost DNS lookup in nsProfileLock.cpp Instead of using the local computer's IP address within symlink-based profile lock signatures, always use 127.0.0.1. --- toolkit/profile/nsProfileLock.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/toolkit/profile/nsProfileLock.cpp b/toolkit/profile/nsProfileLock.cpp index 01818d32e6f7..adccfa4dd6d4 100644 --- a/toolkit/profile/nsProfileLock.cpp +++ b/toolkit/profile/nsProfileLock.cpp @@ -289,18 +289,17 @@ nsresult nsProfileLock::LockWithSymlink(nsIFile* aLockFile, if (!mReplacedLockTime) aLockFile->GetLastModifiedTimeOfLink(&mReplacedLockTime); + // For Tor Browser, avoid a DNS lookup here so the Tor network is not + // bypassed. Instead, always use 127.0.0.1 for the IP address portion + // of the lock signature, which may cause the browser to refuse to + // start in the rare event that all of the following conditions are met: + // 1. The browser profile is on a network file system. + // 2. The file system does not support fcntl() locking. + // 3. Tor Browser is run from two different computers at the same time. + struct in_addr inaddr; inaddr.s_addr = htonl(INADDR_LOOPBACK); - char hostname[256]; - PRStatus status = PR_GetSystemInfo(PR_SI_HOSTNAME, hostname, sizeof hostname); - if (status == PR_SUCCESS) { - char netdbbuf[PR_NETDB_BUF_SIZE]; - PRHostEnt hostent; - status = PR_GetHostByName(hostname, netdbbuf, sizeof netdbbuf, &hostent); - if (status == PR_SUCCESS) memcpy(&inaddr, hostent.h_addr, sizeof inaddr); - } - mozilla::SmprintfPointer signature = mozilla::Smprintf("%s:%s%lu", inet_ntoa(inaddr), aHaveFcntlLock ? "+" : "", (unsigned long)getpid());
1 0
0 0
[tor-browser/tor-browser-84.0-10.5-1] Bug 19273: Avoid JavaScript patching of the external app helper dialog.
by sysrqb@torproject.org 09 Dec '20

09 Dec '20
commit 8bc1b79fdce529476c067eab517eb702ac6bf066 Author: Kathy Brade <brade(a)pearlcrescent.com> Date: Tue Jun 28 15:13:05 2016 -0400 Bug 19273: Avoid JavaScript patching of the external app helper dialog. When handling an external URI or downloading a file, invoke Torbutton's external app blocker component (which will present a download warning dialog unless the user has checked the "Automatically download files from now on" box). For e10s compatibility, avoid using a modal dialog and instead use a callback interface (nsIHelperAppWarningLauncher) to allow Torbutton to indicate the user's desire to cancel or continue each request. Other bugs fixed: Bug 21766: Crash with e10s enabled while trying to download a file Bug 21886: Download is stalled in non-e10s mode Bug 22471: Downloading files via the PDF viewer download button is broken Bug 22472: Fix FTP downloads when external helper app dialog is shown Bug 22610: Avoid crashes when canceling external helper app downloads Bug 22618: Downloading pdf file via file:/// is stalling --- .../exthandler/nsExternalHelperAppService.cpp | 172 ++++++++++++++++++--- uriloader/exthandler/nsExternalHelperAppService.h | 3 + .../exthandler/nsIExternalHelperAppService.idl | 47 ++++++ 3 files changed, 204 insertions(+), 18 deletions(-) diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp index 16b7be9b364a..8028eaeafaab 100644 --- a/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -133,6 +133,9 @@ static const char NEVER_ASK_FOR_SAVE_TO_DISK_PREF[] = static const char NEVER_ASK_FOR_OPEN_FILE_PREF[] = "browser.helperApps.neverAsk.openFile"; +static const char WARNING_DIALOG_CONTRACT_ID[] = + "@torproject.org/torbutton-extAppBlocker;1"; + // Helper functions for Content-Disposition headers /** @@ -405,6 +408,22 @@ static nsresult GetDownloadDirectory(nsIFile** _directory, return NS_OK; } +static already_AddRefed<nsIInterfaceRequestor> GetDialogParentAux( + BrowsingContext* aBrowsingContext, nsIInterfaceRequestor* aWindowContext) { + nsCOMPtr<nsIInterfaceRequestor> dialogParent = aWindowContext; + + if (!dialogParent && aBrowsingContext) { + dialogParent = do_QueryInterface(aBrowsingContext->GetDOMWindow()); + } + if (!dialogParent && aBrowsingContext && XRE_IsParentProcess()) { + RefPtr<Element> element = aBrowsingContext->Top()->GetEmbedderElement(); + if (element) { + dialogParent = do_QueryInterface(element->OwnerDoc()->GetWindow()); + } + } + return dialogParent.forget(); +} + /** * Structure for storing extension->type mappings. * @see defaultMimeEntries @@ -624,6 +643,92 @@ static const char* descriptionOverwriteExtensions[] = { "avif", "pdf", "svg", "webp", "xml", }; +////////////////////////////////////////////////////////////////////////////////////////////////////// +// begin nsExternalLoadURIHandler class definition and implementation +////////////////////////////////////////////////////////////////////////////////////////////////////// +class nsExternalLoadURIHandler final : public nsIHelperAppWarningLauncher { + public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSIHELPERAPPWARNINGLAUNCHER + + nsExternalLoadURIHandler(nsIHandlerInfo* aHandlerInfo, nsIURI* aURI, + nsIPrincipal* aTriggeringPrincipal, + BrowsingContext* aBrowsingContext); + + protected: + ~nsExternalLoadURIHandler(); + + nsCOMPtr<nsIHandlerInfo> mHandlerInfo; + nsCOMPtr<nsIURI> mURI; + nsCOMPtr<nsIPrincipal> mTriggeringPrincipal; + RefPtr<BrowsingContext> mBrowsingContext; + nsCOMPtr<nsIHelperAppWarningDialog> mWarningDialog; +}; + +NS_IMPL_ADDREF(nsExternalLoadURIHandler) +NS_IMPL_RELEASE(nsExternalLoadURIHandler) + +NS_INTERFACE_MAP_BEGIN(nsExternalLoadURIHandler) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIHelperAppWarningLauncher) + NS_INTERFACE_MAP_ENTRY(nsIHelperAppWarningLauncher) +NS_INTERFACE_MAP_END + +nsExternalLoadURIHandler::nsExternalLoadURIHandler( + nsIHandlerInfo* aHandlerInfo, nsIURI* aURI, + nsIPrincipal* aTriggeringPrincipal, BrowsingContext* aBrowsingContext) + : mHandlerInfo(aHandlerInfo), + mURI(aURI), + mTriggeringPrincipal(aTriggeringPrincipal), + mBrowsingContext(aBrowsingContext) + +{ + nsresult rv = NS_OK; + mWarningDialog = do_CreateInstance(WARNING_DIALOG_CONTRACT_ID, &rv); + if (NS_SUCCEEDED(rv) && mWarningDialog) { + // This will create a reference cycle (the dialog holds a reference to us + // as nsIHelperAppWarningLauncher), which will be broken in ContinueRequest + // or CancelRequest. + nsCOMPtr<nsIInterfaceRequestor> dialogParent = + GetDialogParentAux(aBrowsingContext, nullptr); + rv = mWarningDialog->MaybeShow(this, dialogParent); + } + + if (NS_FAILED(rv)) { + // If for some reason we could not open the download warning prompt, + // continue with the request. + ContinueRequest(); + } +} + +nsExternalLoadURIHandler::~nsExternalLoadURIHandler() {} + +NS_IMETHODIMP nsExternalLoadURIHandler::ContinueRequest() { + MOZ_ASSERT(mURI); + MOZ_ASSERT(mHandlerInfo); + + // Break our reference cycle with the download warning dialog (set up in + // LoadURI). + mWarningDialog = nullptr; + + nsresult rv = NS_OK; + nsCOMPtr<nsIContentDispatchChooser> chooser = + do_CreateInstance("@mozilla.org/content-dispatch-chooser;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + return chooser->HandleURI(mHandlerInfo, mURI, mTriggeringPrincipal, + mBrowsingContext); +} + +NS_IMETHODIMP nsExternalLoadURIHandler::CancelRequest(nsresult aReason) { + NS_ENSURE_ARG(NS_FAILED(aReason)); + + // Break our reference cycle with the download warning dialog (set up in + // LoadURI). + mWarningDialog = nullptr; + + return NS_OK; +} + static StaticRefPtr<nsExternalHelperAppService> sExtHelperAppSvcSingleton; /** @@ -650,6 +755,9 @@ nsExternalHelperAppService::GetSingleton() { return do_AddRef(sExtHelperAppSvcSingleton); } +////////////////////////////////////////////////////////////////////////////////////////////////////// +// nsExternalHelperAppService definition and implementation +////////////////////////////////////////////////////////////////////////////////////////////////////// NS_IMPL_ISUPPORTS(nsExternalHelperAppService, nsIExternalHelperAppService, nsPIExternalAppLauncher, nsIExternalProtocolService, nsIMIMEService, nsIObserver, nsISupportsWeakReference) @@ -1093,12 +1201,13 @@ nsExternalHelperAppService::LoadURI(nsIURI* aURI, rv = GetProtocolHandlerInfo(scheme, getter_AddRefs(handler)); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr<nsIContentDispatchChooser> chooser = - do_CreateInstance("@mozilla.org/content-dispatch-chooser;1", &rv); - NS_ENSURE_SUCCESS(rv, rv); + RefPtr<nsExternalLoadURIHandler> h = new nsExternalLoadURIHandler( + handler, uri, aTriggeringPrincipal, aBrowsingContext); + if (!h) { + return NS_ERROR_OUT_OF_MEMORY; + } - return chooser->HandleURI(handler, uri, aTriggeringPrincipal, - aBrowsingContext); + return NS_OK; } ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1243,6 +1352,7 @@ NS_INTERFACE_MAP_BEGIN(nsExternalAppHandler) NS_INTERFACE_MAP_ENTRY(nsIStreamListener) NS_INTERFACE_MAP_ENTRY(nsIRequestObserver) NS_INTERFACE_MAP_ENTRY(nsIHelperAppLauncher) + NS_INTERFACE_MAP_ENTRY(nsIHelperAppWarningLauncher) NS_INTERFACE_MAP_ENTRY(nsICancelable) NS_INTERFACE_MAP_ENTRY(nsIBackgroundFileSaverObserver) NS_INTERFACE_MAP_ENTRY(nsINamed) @@ -1639,18 +1749,7 @@ void nsExternalAppHandler::MaybeApplyDecodingForExtension( already_AddRefed<nsIInterfaceRequestor> nsExternalAppHandler::GetDialogParent() { - nsCOMPtr<nsIInterfaceRequestor> dialogParent = mWindowContext; - - if (!dialogParent && mBrowsingContext) { - dialogParent = do_QueryInterface(mBrowsingContext->GetDOMWindow()); - } - if (!dialogParent && mBrowsingContext && XRE_IsParentProcess()) { - RefPtr<Element> element = mBrowsingContext->Top()->GetEmbedderElement(); - if (element) { - dialogParent = do_QueryInterface(element->OwnerDoc()->GetWindow()); - } - } - return dialogParent.forget(); + return GetDialogParentAux(mBrowsingContext, mWindowContext); } NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { @@ -1781,6 +1880,34 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { loadInfo->SetForceAllowDataURI(true); } + mWarningDialog = do_CreateInstance(WARNING_DIALOG_CONTRACT_ID, &rv); + if (NS_SUCCEEDED(rv) && mWarningDialog) { + // This will create a reference cycle (the dialog holds a reference to us + // as nsIHelperAppWarningLauncher), which will be broken in ContinueRequest + // or CancelRequest. + nsCOMPtr<nsIInterfaceRequestor> dialogParent = GetDialogParent(); + rv = mWarningDialog->MaybeShow(this, dialogParent); + } + + if (NS_FAILED(rv)) { + // If for some reason we could not open the download warning prompt, + // continue with the request. + ContinueRequest(); + } + + return NS_OK; +} + +NS_IMETHODIMP nsExternalAppHandler::ContinueRequest() { + nsAutoCString MIMEType; + if (mMimeInfo) { + mMimeInfo->GetMIMEType(MIMEType); + } + + // Break our reference cycle with the download warning dialog (set up in + // OnStartRequest). + mWarningDialog = nullptr; + // now that the temp file is set up, find out if we need to invoke a dialog // asking the user what they want us to do with this content... @@ -1864,6 +1991,7 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { action = nsIMIMEInfo::saveToDisk; } + nsresult rv = NS_OK; if (alwaysAsk) { // Display the dialog mDialog = do_CreateInstance(NS_HELPERAPPLAUNCHERDLG_CONTRACTID, &rv); @@ -1921,6 +2049,14 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { return NS_OK; } +NS_IMETHODIMP nsExternalAppHandler::CancelRequest(nsresult aReason) { + // Break our reference cycle with the download warning dialog (set up in + // OnStartRequest). + mWarningDialog = nullptr; + + return Cancel(aReason); +} + // Convert error info into proper message text and send OnStatusChange // notification to the dialog progress listener or nsITransfer implementation. void nsExternalAppHandler::SendStatusChange(ErrorType type, nsresult rv, @@ -2585,7 +2721,7 @@ NS_IMETHODIMP nsExternalAppHandler::Cancel(nsresult aReason) { } // Break our reference cycle with the helper app dialog (set up in - // OnStartRequest) + // ContinueRequest) mDialog = nullptr; mRequest = nullptr; diff --git a/uriloader/exthandler/nsExternalHelperAppService.h b/uriloader/exthandler/nsExternalHelperAppService.h index b49686159aa7..e7174570e0bb 100644 --- a/uriloader/exthandler/nsExternalHelperAppService.h +++ b/uriloader/exthandler/nsExternalHelperAppService.h @@ -219,6 +219,7 @@ class nsExternalHelperAppService : public nsIExternalHelperAppService, */ class nsExternalAppHandler final : public nsIStreamListener, public nsIHelperAppLauncher, + public nsIHelperAppWarningLauncher, public nsIBackgroundFileSaverObserver, public nsINamed { public: @@ -226,6 +227,7 @@ class nsExternalAppHandler final : public nsIStreamListener, NS_DECL_NSISTREAMLISTENER NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSIHELPERAPPLAUNCHER + NS_DECL_NSIHELPERAPPWARNINGLAUNCHER NS_DECL_NSICANCELABLE NS_DECL_NSIBACKGROUNDFILESAVEROBSERVER NS_DECL_NSINAMED @@ -497,6 +499,7 @@ class nsExternalAppHandler final : public nsIStreamListener, nsCOMPtr<nsITransfer> mTransfer; nsCOMPtr<nsIHelperAppLauncherDialog> mDialog; + nsCOMPtr<nsIHelperAppWarningDialog> mWarningDialog; /** diff --git a/uriloader/exthandler/nsIExternalHelperAppService.idl b/uriloader/exthandler/nsIExternalHelperAppService.idl index 657e15bc0742..ebdb1cdacf78 100644 --- a/uriloader/exthandler/nsIExternalHelperAppService.idl +++ b/uriloader/exthandler/nsIExternalHelperAppService.idl @@ -177,3 +177,50 @@ interface nsIHelperAppLauncher : nsICancelable */ readonly attribute uint64_t browsingContextId; }; + +/** + * nsIHelperAppWarningLauncher is implemented by two classes: + * nsExternalLoadURIHandler + * nsExternalAppHandler + */ +[scriptable, uuid(cffd508b-4aaf-43ad-99c6-671d35cbc558)] +interface nsIHelperAppWarningLauncher : nsISupports +{ + /** + * Callback invoked by the external app warning dialog to continue the + * request. + * NOTE: This will release the reference to the nsIHelperAppWarningDialog. + */ + void continueRequest(); + + /** + * Callback invoked by the external app warning dialog to cancel the request. + * NOTE: This will release the reference to the nsIHelperAppWarningDialog. + * + * @param aReason + * Pass a failure code to indicate the reason why this operation is + * being canceled. It is an error to pass a success code. + */ + void cancelRequest(in nsresult aReason); +}; + +/** + * nsIHelperAppWarningDialog is implemented by Torbutton's external app + * blocker (src/components/external-app-blocker.js). + */ +[scriptable, uuid(f4899a3f-0df3-42cc-9db8-bdf599e5a208)] +interface nsIHelperAppWarningDialog : nsISupports +{ + /** + * Possibly show a launch warning dialog (it will not be shown if the user + * has chosen to not see the warning again). + * + * @param aLauncher + * A nsIHelperAppWarningLauncher to be invoked after the user confirms + * or cancels the download. + * @param aWindowContext + * The window associated with the download. + */ + void maybeShow(in nsIHelperAppWarningLauncher aLauncher, + in nsISupports aWindowContext); +};
1 0
0 0
[tor-browser/tor-browser-84.0-10.5-1] Bug 18821: Disable libmdns for Android and Desktop
by sysrqb@torproject.org 09 Dec '20

09 Dec '20
commit 883a32c319453f7c4b208a2644db81b71f52cb81 Author: Georg Koppen <gk(a)torproject.org> Date: Wed Apr 20 14:34:50 2016 +0000 Bug 18821: Disable libmdns for Android and Desktop There should be no need to remove the OS X support introduced in https://bugzilla.mozilla.org/show_bug.cgi?id=1225726 as enabling this is governed by a preference (which is actually set to `false`). However, we remove it at build time as well (defense in depth). This is basically a backout of the relevant passages of https://hg.mozilla.org/mozilla-central/rev/6bfb430de85d, https://hg.mozilla.org/mozilla-central/rev/609b337bf7ab and https://hg.mozilla.org/mozilla-central/rev/8e092ec5fbbd. Fixed bug 21861 (Disable additional mDNS code to avoid proxy bypasses) as well. --- dom/presentation/provider/components.conf | 10 ---------- dom/presentation/provider/moz.build | 1 - netwerk/dns/mdns/libmdns/components.conf | 15 --------------- netwerk/dns/mdns/libmdns/moz.build | 28 ---------------------------- 4 files changed, 54 deletions(-) diff --git a/dom/presentation/provider/components.conf b/dom/presentation/provider/components.conf index 04cb28ec757e..56994ed7cd94 100644 --- a/dom/presentation/provider/components.conf +++ b/dom/presentation/provider/components.conf @@ -6,9 +6,6 @@ categories = {} -if buildconfig.substs['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'android'): - categories["presentation-device-provider"] = "MulticastDNSDeviceProvider" - Classes = [ { 'cid': '{f4079b8b-ede5-4b90-a112-5b415a931deb}', @@ -16,11 +13,4 @@ Classes = [ 'jsm': 'resource://gre/modules/PresentationControlService.jsm', 'constructor': 'PresentationControlService', }, - { - 'cid': '{814f947a-52f7-41c9-94a1-3684797284ac}', - 'contract_ids': ['@mozilla.org/presentation-device/multicastdns-provider;1'], - 'type': 'mozilla::dom::presentation::MulticastDNSDeviceProvider', - 'headers': ['/dom/presentation/provider/MulticastDNSDeviceProvider.h'], - 'categories': categories, - }, ] diff --git a/dom/presentation/provider/moz.build b/dom/presentation/provider/moz.build index f6c4527d2cdf..9fab92997787 100644 --- a/dom/presentation/provider/moz.build +++ b/dom/presentation/provider/moz.build @@ -8,7 +8,6 @@ EXTRA_JS_MODULES += ["PresentationControlService.jsm"] UNIFIED_SOURCES += [ "DeviceProviderHelpers.cpp", - "MulticastDNSDeviceProvider.cpp", ] XPCOM_MANIFESTS += [ diff --git a/netwerk/dns/mdns/libmdns/components.conf b/netwerk/dns/mdns/libmdns/components.conf index 6e64140c820e..1b50dbf673a4 100644 --- a/netwerk/dns/mdns/libmdns/components.conf +++ b/netwerk/dns/mdns/libmdns/components.conf @@ -5,20 +5,5 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. Classes = [ - { - 'cid': '{14a50f2b-7ff6-48a5-88e3-615fd111f5d3}', - 'contract_ids': ['@mozilla.org/toolkit/components/mdnsresponder/dns-info;1'], - 'type': 'mozilla::net::nsDNSServiceInfo', - 'headers': ['/netwerk/dns/mdns/libmdns/nsDNSServiceInfo.h'], - }, ] -if buildconfig.substs['MOZ_WIDGET_TOOLKIT'] != 'cocoa': - Classes += [ - { - 'cid': '{f9346d98-f27a-4e89-b744-493843416480}', - 'contract_ids': ['@mozilla.org/toolkit/components/mdnsresponder/dns-sd;1'], - 'jsm': 'resource://gre/modules/DNSServiceDiscovery.jsm', - 'constructor': 'nsDNSServiceDiscovery', - }, - ] diff --git a/netwerk/dns/mdns/libmdns/moz.build b/netwerk/dns/mdns/libmdns/moz.build index f9c025fa823e..e6e70a6d803c 100644 --- a/netwerk/dns/mdns/libmdns/moz.build +++ b/netwerk/dns/mdns/libmdns/moz.build @@ -4,34 +4,6 @@ # 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/. -if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa": - UNIFIED_SOURCES += [ - "MDNSResponderOperator.cpp", - "MDNSResponderReply.cpp", - "nsDNSServiceDiscovery.cpp", - ] - - LOCAL_INCLUDES += [ - "/netwerk/base", - ] - -else: - EXTRA_JS_MODULES += [ - "DNSServiceDiscovery.jsm", - "fallback/DataReader.jsm", - "fallback/DataWriter.jsm", - "fallback/DNSPacket.jsm", - "fallback/DNSRecord.jsm", - "fallback/DNSResourceRecord.jsm", - "fallback/DNSTypes.jsm", - "fallback/MulticastDNS.jsm", - ] - - if CONFIG["MOZ_WIDGET_TOOLKIT"] == "android": - EXTRA_JS_MODULES += [ - "MulticastDNSAndroid.jsm", - ] - UNIFIED_SOURCES += [ "nsDNSServiceInfo.cpp", ]
1 0
0 0
[tor-browser/tor-browser-84.0-10.5-1] Bug 21724: Make Firefox and Tor Browser distinct macOS apps
by sysrqb@torproject.org 09 Dec '20

09 Dec '20
commit 27a3f138896eb904d5e0d39de97ac028e67e621d Author: teor <teor2345(a)gmail.com> Date: Mon Mar 13 23:06:23 2017 +1100 Bug 21724: Make Firefox and Tor Browser distinct macOS apps When macOS opens a document or selects a default browser, it sometimes uses the CFBundleSignature. Changing from the Firefox MOZB signature to a different signature TORB allows macOS to distinguish between Firefox and Tor Browser. --- browser/app/Makefile.in | 2 +- browser/app/macbuild/Contents/Info.plist.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/app/Makefile.in b/browser/app/Makefile.in index 54d6b43fe126..8dd3a9a65661 100644 --- a/browser/app/Makefile.in +++ b/browser/app/Makefile.in @@ -102,5 +102,5 @@ ifdef MOZ_UPDATER mv -f '$(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater' '$(dist_dest)/Contents/Library/LaunchServices' ln -s ../../../../Library/LaunchServices/org.mozilla.updater '$(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater' endif - printf APPLMOZB > '$(dist_dest)/Contents/PkgInfo' + printf APPLTORB > '$(dist_dest)/Contents/PkgInfo' endif diff --git a/browser/app/macbuild/Contents/Info.plist.in b/browser/app/macbuild/Contents/Info.plist.in index fb5e6993ea9d..1d376c8d83d6 100644 --- a/browser/app/macbuild/Contents/Info.plist.in +++ b/browser/app/macbuild/Contents/Info.plist.in @@ -179,7 +179,7 @@ <key>CFBundleShortVersionString</key> <string>@APP_VERSION@</string> <key>CFBundleSignature</key> - <string>MOZB</string> + <string>TORB</string> <key>CFBundleURLTypes</key> <array> <dict>
1 0
0 0
[tor-browser/tor-browser-84.0-10.5-1] Bug 16940: After update, load local change notes.
by sysrqb@torproject.org 09 Dec '20

09 Dec '20
commit f792cdbfa82c099871fc440d51865a8fb7875fcf Author: Kathy Brade <brade(a)pearlcrescent.com> Date: Wed Nov 25 11:36:20 2015 -0500 Bug 16940: After update, load local change notes. Add an about:tbupdate page that displays the first section from TorBrowser/Docs/ChangeLog.txt and includes a link to the remote post-update page (typically our blog entry for the release). Always load about:tbupdate in a content process, but implement the code that reads the file system (changelog) in the chrome process for compatibility with future sandboxing efforts. Also fix bug 29440. Now about:tbupdate is styled as a fairly simple changelog page that is designed to be displayed via a link that is on about:tor. --- browser/actors/AboutTBUpdateChild.jsm | 12 +++ browser/actors/AboutTBUpdateParent.jsm | 120 +++++++++++++++++++++ browser/actors/moz.build | 6 ++ .../base/content/abouttbupdate/aboutTBUpdate.css | 74 +++++++++++++ .../base/content/abouttbupdate/aboutTBUpdate.js | 27 +++++ .../base/content/abouttbupdate/aboutTBUpdate.xhtml | 39 +++++++ browser/base/content/browser-siteIdentity.js | 2 +- browser/base/content/browser.js | 4 + browser/base/jar.mn | 5 + browser/components/BrowserContentHandler.jsm | 55 +++++++--- browser/components/BrowserGlue.jsm | 15 +++ browser/components/about/AboutRedirector.cpp | 6 ++ browser/components/about/components.conf | 3 + browser/components/moz.build | 5 +- .../locales/en-US/chrome/browser/aboutTBUpdate.dtd | 8 ++ browser/locales/jar.mn | 3 + toolkit/modules/RemotePageAccessManager.jsm | 5 + 17 files changed, 373 insertions(+), 16 deletions(-) diff --git a/browser/actors/AboutTBUpdateChild.jsm b/browser/actors/AboutTBUpdateChild.jsm new file mode 100644 index 000000000000..4670da19b3db --- /dev/null +++ b/browser/actors/AboutTBUpdateChild.jsm @@ -0,0 +1,12 @@ +// Copyright (c) 2020, The Tor Project, Inc. +// See LICENSE for licensing information. +// +// vim: set sw=2 sts=2 ts=8 et syntax=javascript: + +var EXPORTED_SYMBOLS = ["AboutTBUpdateChild"]; + +const { RemotePageChild } = ChromeUtils.import( + "resource://gre/actors/RemotePageChild.jsm" +); + +class AboutTBUpdateChild extends RemotePageChild {} diff --git a/browser/actors/AboutTBUpdateParent.jsm b/browser/actors/AboutTBUpdateParent.jsm new file mode 100644 index 000000000000..56a10394565a --- /dev/null +++ b/browser/actors/AboutTBUpdateParent.jsm @@ -0,0 +1,120 @@ +// Copyright (c) 2020, The Tor Project, Inc. +// See LICENSE for licensing information. +// +// vim: set sw=2 sts=2 ts=8 et syntax=javascript: + +"use strict"; + +this.EXPORTED_SYMBOLS = ["AboutTBUpdateParent"]; + +const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); +const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm"); +const { AppConstants } = ChromeUtils.import( + "resource://gre/modules/AppConstants.jsm" +); + +const kRequestUpdateMessageName = "FetchUpdateData"; + +/** + * This code provides services to the about:tbupdate page. Whenever + * about:tbupdate needs to do something chrome-privileged, it sends a + * message that's handled here. It is modeled after Mozilla's about:home + * implementation. + */ +class AboutTBUpdateParent extends JSWindowActorParent { + receiveMessage(aMessage) { + if (aMessage.name == kRequestUpdateMessageName) { + return this.releaseNoteInfo; + } + return undefined; + } + + get moreInfoURL() { + try { + return Services.prefs.getCharPref("torbrowser.post_update.url"); + } catch (e) {} + + // Use the default URL as a fallback. + return Services.urlFormatter.formatURLPref("startup.homepage_override_url"); + } + + // Read the text from the beginning of the changelog file that is located + // at TorBrowser/Docs/ChangeLog.txt and return an object that contains + // the following properties: + // version e.g., Tor Browser 8.5 + // releaseDate e.g., March 31 2019 + // releaseNotes details of changes (lines 2 - end of ChangeLog.txt) + // We attempt to parse the first line of ChangeLog.txt to extract the + // version and releaseDate. If parsing fails, we return the entire first + // line in version and omit releaseDate. + // + // On Mac OS, when building with --enable-tor-browser-data-outside-app-dir + // to support Gatekeeper signing, the ChangeLog.txt file is located in + // TorBrowser.app/Contents/Resources/TorBrowser/Docs/. + get releaseNoteInfo() { + let info = { moreInfoURL: this.moreInfoURL }; + + try { + let f; + if (AppConstants.TOR_BROWSER_DATA_OUTSIDE_APP_DIR) { + // "XREExeF".parent is the directory that contains firefox, i.e., + // Browser/ or, on Mac OS, TorBrowser.app/Contents/MacOS/. + f = Services.dirsvc.get("XREExeF", Ci.nsIFile).parent; + if (AppConstants.platform === "macosx") { + f = f.parent; + f.append("Resources"); + } + f.append("TorBrowser"); + } else { + // "DefProfRt" is .../TorBrowser/Data/Browser + f = Services.dirsvc.get("DefProfRt", Ci.nsIFile); + f = f.parent.parent; // Remove "Data/Browser" + } + + f.append("Docs"); + f.append("ChangeLog.txt"); + + let fs = Cc["@mozilla.org/network/file-input-stream;1"].createInstance( + Ci.nsIFileInputStream + ); + fs.init(f, -1, 0, 0); + let s = NetUtil.readInputStreamToString(fs, fs.available()); + fs.close(); + + // Truncate at the first empty line. + s = s.replace(/[\r\n][\r\n][\s\S]*$/m, ""); + + // Split into first line (version plus releaseDate) and + // remainder (releaseNotes). + // This first match() uses multiline mode with two capture groups: + // first line: (.*$) + // remaining lines: ([\s\S]+) + // [\s\S] matches all characters including end of line. This trick + // is needed because when using JavaScript regex in multiline mode, + // . does not match an end of line character. + let matchArray = s.match(/(.*$)\s*([\s\S]+)/m); + if (matchArray && matchArray.length == 3) { + info.releaseNotes = matchArray[2]; + let line1 = matchArray[1]; + // Extract the version and releaseDate. The first line looks like: + // Tor Browser 8.5 -- May 1 2019 + // The regex uses two capture groups: + // text that does not include a hyphen: (^[^-]*) + // remaining text: (.*$) + // In between we match optional whitespace, one or more hyphens, and + // optional whitespace by using: \s*-+\s* + matchArray = line1.match(/(^[^-]*)\s*-+\s*(.*$)/); + if (matchArray && matchArray.length == 3) { + info.version = matchArray[1]; + info.releaseDate = matchArray[2]; + } else { + info.version = line1; // Match failed: return entire line in version. + } + } else { + info.releaseNotes = s; // Only one line: use as releaseNotes. + } + } catch (e) {} + + return info; + } +} diff --git a/browser/actors/moz.build b/browser/actors/moz.build index 1f9f8ef1c032..72707d4e9bc8 100644 --- a/browser/actors/moz.build +++ b/browser/actors/moz.build @@ -87,3 +87,9 @@ FINAL_TARGET_FILES.actors += [ "WebRTCChild.jsm", "WebRTCParent.jsm", ] + +if CONFIG["TOR_BROWSER_UPDATE"]: + FINAL_TARGET_FILES.actors += [ + "AboutTBUpdateChild.jsm", + "AboutTBUpdateParent.jsm", + ] diff --git a/browser/base/content/abouttbupdate/aboutTBUpdate.css b/browser/base/content/abouttbupdate/aboutTBUpdate.css new file mode 100644 index 000000000000..7c1a34b77f17 --- /dev/null +++ b/browser/base/content/abouttbupdate/aboutTBUpdate.css @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2019, The Tor Project, Inc. + * See LICENSE for licensing information. + * + * vim: set sw=2 sts=2 ts=8 et syntax=css: + */ + +:root { + --abouttor-text-color: white; + --abouttor-bg-toron-color: #420C5D; +} + +body { + font-family: Helvetica, Arial, sans-serif; + color: var(--abouttor-text-color); + background-color: var(--abouttor-bg-toron-color); + background-attachment: fixed; + background-size: 100% 100%; +} + +a { + color: var(--abouttor-text-color); +} + +.two-column-grid { + display: inline-grid; + grid-template-columns: auto auto; + grid-column-gap: 50px; + margin: 10px 0px 0px 50px; +} + +.two-column-grid div { + margin-top: 40px; + align-self: baseline; /* Align baseline of text across the row. */ +} + +.label-column { + font-size: 14px; + font-weight: 400; +} + +/* + * Use a reduced top margin to bring the row that contains the + * "visit our website" link closer to the row that precedes it. This + * looks better because the "visit our website" row does not have a + * label in the left column. + */ +div.more-info-row { + margin-top: 5px; + font-size: 14px; +} + +#version-content { + font-size: 50px; + font-weight: 300; +} + +body:not([havereleasedate]) .release-date-cell { + display: none; +} + +#releasedate-content { + font-size: 17px; +} + +#releasenotes-label { + align-self: start; /* Anchor "Release Notes" label at the top. */ +} + +#releasenotes-content { + font-family: monospace; + font-size: 15px; + white-space: pre; +} diff --git a/browser/base/content/abouttbupdate/aboutTBUpdate.js b/browser/base/content/abouttbupdate/aboutTBUpdate.js new file mode 100644 index 000000000000..ec070e2cb131 --- /dev/null +++ b/browser/base/content/abouttbupdate/aboutTBUpdate.js @@ -0,0 +1,27 @@ +// Copyright (c) 2020, The Tor Project, Inc. +// See LICENSE for licensing information. +// +// vim: set sw=2 sts=2 ts=8 et syntax=javascript: + +/* eslint-env mozilla/frame-script */ + +// aData may contain the following string properties: +// version +// releaseDate +// moreInfoURL +// releaseNotes +function onUpdate(aData) { + document.getElementById("version-content").textContent = aData.version; + if (aData.releaseDate) { + document.body.setAttribute("havereleasedate", "true"); + document.getElementById("releasedate-content").textContent = + aData.releaseDate; + } + if (aData.moreInfoURL) { + document.getElementById("infolink").setAttribute("href", aData.moreInfoURL); + } + document.getElementById("releasenotes-content").textContent = + aData.releaseNotes; +} + +RPMSendQuery("FetchUpdateData").then(onUpdate); diff --git a/browser/base/content/abouttbupdate/aboutTBUpdate.xhtml b/browser/base/content/abouttbupdate/aboutTBUpdate.xhtml new file mode 100644 index 000000000000..8489cfef5083 --- /dev/null +++ b/browser/base/content/abouttbupdate/aboutTBUpdate.xhtml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!DOCTYPE html [ + <!ENTITY % htmlDTD + PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "DTD/xhtml1-strict.dtd"> + %htmlDTD; + <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd"> + %globalDTD; + <!ENTITY % tbUpdateDTD SYSTEM "chrome://browser/locale/aboutTBUpdate.dtd"> + %tbUpdateDTD; +]> + +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <meta http-equiv="Content-Security-Policy" content="default-src chrome:; object-src 'none'" /> + <title>&aboutTBUpdate.changelogTitle;</title> + <link rel="stylesheet" type="text/css" + href="chrome://browser/content/abouttbupdate/aboutTBUpdate.css"/> + <script src="chrome://browser/content/abouttbupdate/aboutTBUpdate.js" + type="text/javascript"/> +</head> +<body dir="&locale.dir;"> +<div class="two-column-grid"> + <div class="label-column">&aboutTBUpdate.version;</div> + <div id="version-content"/> + + <div class="label-column release-date-cell">&aboutTBUpdate.releaseDate;</div> + <div id="releasedate-content" class="release-date-cell"/> + + <div class="more-info-row"/> + <div class="more-info-row">&aboutTBUpdate.linkPrefix;<a id="infolink">&aboutTBUpdate.linkLabel;</a>&aboutTBUpdate.linkSuffix;</div> + + <div id="releasenotes-label" + class="label-column">&aboutTBUpdate.releaseNotes;</div> + <div id="releasenotes-content"></div> +</div> +</body> +</html> diff --git a/browser/base/content/browser-siteIdentity.js b/browser/base/content/browser-siteIdentity.js index abdb81499533..a936b7f4826b 100644 --- a/browser/base/content/browser-siteIdentity.js +++ b/browser/base/content/browser-siteIdentity.js @@ -57,7 +57,7 @@ var gIdentityHandler = { * RegExp used to decide if an about url should be shown as being part of * the browser UI. */ - _secureInternalPages: /^(?:accounts|addons|cache|certificate|config|crashes|downloads|license|logins|preferences|protections|rights|sessionrestore|support|welcomeback|ion)(?:[?#]|$)/i, + _secureInternalPages: (AppConstants.TOR_BROWSER_UPDATE ? /^(?:accounts|addons|cache|certificate|config|crashes|downloads|license|logins|preferences|protections|rights|sessionrestore|support|welcomeback|ion|tor|tbupdate)(?:[?#]|$)/i : /^(?:accounts|addons|cache|certificate|config|crashes|downloads|license|logins|preferences|protections|rights|sessionrestore|support|welcomeback|ion|tor)(?:[?#]|$)/i), /** * Whether the established HTTPS connection is considered "broken". diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index a8306c602601..9abba4bc420c 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -638,6 +638,10 @@ var gInitialPages = [ "about:newinstall", ]; +if (AppConstants.TOR_BROWSER_UPDATE) { + gInitialPages.push("about:tbupdate"); +} + function isInitialPage(url) { if (!(url instanceof Ci.nsIURI)) { try { diff --git a/browser/base/jar.mn b/browser/base/jar.mn index 471544f6b7f7..d6c9e31c2c95 100644 --- a/browser/base/jar.mn +++ b/browser/base/jar.mn @@ -31,6 +31,11 @@ browser.jar: content/browser/aboutTabCrashed.css (content/aboutTabCrashed.css) content/browser/aboutTabCrashed.js (content/aboutTabCrashed.js) content/browser/aboutTabCrashed.xhtml (content/aboutTabCrashed.xhtml) +#ifdef TOR_BROWSER_UPDATE + content/browser/abouttbupdate/aboutTBUpdate.xhtml (content/abouttbupdate/aboutTBUpdate.xhtml) + content/browser/abouttbupdate/aboutTBUpdate.js (content/abouttbupdate/aboutTBUpdate.js) + content/browser/abouttbupdate/aboutTBUpdate.css (content/abouttbupdate/aboutTBUpdate.css) +#endif * content/browser/browser.css (content/browser.css) content/browser/browser.js (content/browser.js) * content/browser/browser.xhtml (content/browser.xhtml) diff --git a/browser/components/BrowserContentHandler.jsm b/browser/components/BrowserContentHandler.jsm index 0a37ca088ca0..ab63c16087f0 100644 --- a/browser/components/BrowserContentHandler.jsm +++ b/browser/components/BrowserContentHandler.jsm @@ -652,6 +652,23 @@ nsBrowserContentHandler.prototype = { } } + // Retrieve the home page early so we can compare it against about:tor + // to decide whether or not we need an override page (second tab) after + // an update was applied. + var startPage = ""; + try { + var choice = prefb.getIntPref("browser.startup.page"); + if (choice == 1 || choice == 3) { + startPage = HomePage.get(); + } + } catch (e) { + Cu.reportError(e); + } + + if (startPage == "about:blank") { + startPage = ""; + } + var override; var overridePage = ""; var additionalPage = ""; @@ -703,6 +720,16 @@ nsBrowserContentHandler.prototype = { // into account because that requires waiting for the session file // to be read. If a crash occurs after updating, before restarting, // we may open the startPage in addition to restoring the session. + // + // Tor Browser: Instead of opening the post-update "override page" + // directly, we ensure that about:tor will be opened in a special + // mode that notifies the user that their browser was updated. + // The about:tor page will provide a link to the override page + // where the user can learn more about the update, as well as a + // link to the Tor Browser changelog page (about:tbupdate). The + // override page URL comes from the openURL attribute within the + // updates.xml file or, if no showURL action is present, from the + // startup.homepage_override_url pref. willRestoreSession = SessionStartup.isAutomaticRestoreEnabled(); overridePage = Services.urlFormatter.formatURLPref( @@ -722,6 +749,20 @@ nsBrowserContentHandler.prototype = { overridePage = overridePage.replace("%OLD_VERSION%", old_mstone); overridePage = overridePage.replace("%OLD_TOR_BROWSER_VERSION%", old_tbversion); +#ifdef TOR_BROWSER_UPDATE + if (overridePage) + { + prefb.setCharPref("torbrowser.post_update.url", overridePage); + prefb.setBoolPref("torbrowser.post_update.shouldNotify", true); + // If the user's homepage is about:tor, we will inform them + // about the update on that page; otherwise, we arrange to + // open about:tor in a secondary tab. + if (startPage === "about:tor") + overridePage = ""; + else + overridePage = "about:tor"; + } +#endif break; case OVERRIDE_NEW_BUILD_ID: if (UpdateManager.readyUpdate) { @@ -794,20 +835,6 @@ nsBrowserContentHandler.prototype = { } } - var startPage = ""; - try { - var choice = prefb.getIntPref("browser.startup.page"); - if (choice == 1 || choice == 3) { - startPage = HomePage.get(); - } - } catch (e) { - Cu.reportError(e); - } - - if (startPage == "about:blank") { - startPage = ""; - } - let skipStartPage = (override == OVERRIDE_NEW_PROFILE || override == OVERRIDE_ALTERNATE_PROFILE) && diff --git a/browser/components/BrowserGlue.jsm b/browser/components/BrowserGlue.jsm index 869a90ef40f9..3725c8f8b7a5 100644 --- a/browser/components/BrowserGlue.jsm +++ b/browser/components/BrowserGlue.jsm @@ -696,6 +696,21 @@ let JSWINDOWACTORS = { }, }; +if (AppConstants.TOR_BROWSER_UPDATE) { + JSWINDOWACTORS["AboutTBUpdate"] = { + parent: { + moduleURI: "resource:///actors/AboutTBUpdateParent.jsm", + }, + child: { + moduleURI: "resource:///actors/AboutTBUpdateChild.jsm", + events: { + DOMWindowCreated: { capture: true }, + }, + }, + matches: ["about:tbupdate"], + }; +} + (function earlyBlankFirstPaint() { let startTime = Cu.now(); if ( diff --git a/browser/components/about/AboutRedirector.cpp b/browser/components/about/AboutRedirector.cpp index 4e17a115072a..169b2862a92a 100644 --- a/browser/components/about/AboutRedirector.cpp +++ b/browser/components/about/AboutRedirector.cpp @@ -120,6 +120,12 @@ static const RedirEntry kRedirMap[] = { nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS}, {"ion", "chrome://browser/content/ion.html", nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT}, +#ifdef TOR_BROWSER_UPDATE + {"tbupdate", "chrome://browser/content/abouttbupdate/aboutTBUpdate.xhtml", + nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | + nsIAboutModule::URI_MUST_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT | + nsIAboutModule::HIDE_FROM_ABOUTABOUT}, +#endif }; static nsAutoCString GetAboutModuleName(nsIURI* aURI) { diff --git a/browser/components/about/components.conf b/browser/components/about/components.conf index 42011d509481..56731d70c386 100644 --- a/browser/components/about/components.conf +++ b/browser/components/about/components.conf @@ -32,6 +32,9 @@ pages = [ 'welcomeback', ] +if defined('TOR_BROWSER_UPDATE'): + pages.append('tbupdate') + Classes = [ { 'cid': '{7e4bb6ad-2fc4-4dc6-89ef-23e8e5ccf980}', diff --git a/browser/components/moz.build b/browser/components/moz.build index ba617de9d82f..7f82f14985fe 100644 --- a/browser/components/moz.build +++ b/browser/components/moz.build @@ -89,11 +89,14 @@ EXTRA_COMPONENTS += [ ] EXTRA_JS_MODULES += [ - "BrowserContentHandler.jsm", "BrowserGlue.jsm", "distribution.js", ] +EXTRA_PP_JS_MODULES += [ + "BrowserContentHandler.jsm", +] + BROWSER_CHROME_MANIFESTS += [ "safebrowsing/content/test/browser.ini", "tests/browser/browser.ini", diff --git a/browser/locales/en-US/chrome/browser/aboutTBUpdate.dtd b/browser/locales/en-US/chrome/browser/aboutTBUpdate.dtd new file mode 100644 index 000000000000..2d1e59b40eaf --- /dev/null +++ b/browser/locales/en-US/chrome/browser/aboutTBUpdate.dtd @@ -0,0 +1,8 @@ +<!ENTITY aboutTBUpdate.changelogTitle "Tor Browser Changelog"> +<!ENTITY aboutTBUpdate.updated "Tor Browser has been updated."> +<!ENTITY aboutTBUpdate.linkPrefix "For the most up-to-date information about this release, "> +<!ENTITY aboutTBUpdate.linkLabel "visit our website"> +<!ENTITY aboutTBUpdate.linkSuffix "."> +<!ENTITY aboutTBUpdate.version "Version"> +<!ENTITY aboutTBUpdate.releaseDate "Release Date"> +<!ENTITY aboutTBUpdate.releaseNotes "Release Notes"> diff --git a/browser/locales/jar.mn b/browser/locales/jar.mn index 62c281b9e68e..454dcf5fdf2f 100644 --- a/browser/locales/jar.mn +++ b/browser/locales/jar.mn @@ -20,6 +20,9 @@ locale/browser/accounts.properties (%chrome/browser/accounts.properties) locale/browser/app-extension-fields.properties (%chrome/browser/app-extension-fields.properties) +#ifdef TOR_BROWSER_UPDATE + locale/browser/aboutTBUpdate.dtd (%chrome/browser/aboutTBUpdate.dtd) +#endif locale/browser/browser.dtd (%chrome/browser/browser.dtd) locale/browser/baseMenuOverlay.dtd (%chrome/browser/baseMenuOverlay.dtd) locale/browser/browser.properties (%chrome/browser/browser.properties) diff --git a/toolkit/modules/RemotePageAccessManager.jsm b/toolkit/modules/RemotePageAccessManager.jsm index dea1789a42ec..1d607b814b94 100644 --- a/toolkit/modules/RemotePageAccessManager.jsm +++ b/toolkit/modules/RemotePageAccessManager.jsm @@ -202,6 +202,11 @@ let RemotePageAccessManager = { RPMAddMessageListener: ["*"], RPMRemoveMessageListener: ["*"], }, + "about:tbupdate": { + RPMSendQuery: [ + "FetchUpdateData", + ], + }, }, /**
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 1360
  • 1361
  • 1362
  • 1363
  • 1364
  • 1365
  • 1366
  • ...
  • 2132
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.