commit 43c5ec54ce50cd08ccc27b02ef2b3ebbef9a02aa Author: Kathy Brade brade@pearlcrescent.com Date: Thu Aug 14 11:39:09 2014 -0400
Bug 4234: Use the Firefox Update Process for TBB.
New configure options: --with-tor-browser-version=VERSION # Pass TBB version throughout build. --enable-tor-browser-update # Enable bundle update behavior. The following files are never updated: TorBrowser/Data/Browser/profiles.ini TorBrowser/Data/Browser/profile.default/bookmarks.html TorBrowser/Data/Tor/torrc --- .mozconfig | 5 +- .mozconfig-mac | 6 +- .mozconfig-mingw | 5 +- accessible/src/Makefile.in | 2 +- accessible/src/shared.mozbuild | 2 +- browser/app/profile/000-tor-browser.js | 8 +- browser/app/profile/firefox.js | 11 +- browser/base/content/aboutDialog.js | 45 +++- browser/branding/official/pref/firefox-branding.js | 4 +- browser/confvars.sh | 19 +- browser/installer/Makefile.in | 4 + browser/installer/removed-files.in | 4 +- config/createprecomplete.py | 14 +- configure.in | 28 ++- js/src/configure.in | 3 - toolkit/modules/debug.js | 1 + toolkit/mozapps/extensions/Makefile.in | 2 +- toolkit/mozapps/update/nsUpdateService.js | 68 +++++- toolkit/mozapps/update/updater/updater.cpp | 245 +++++++++++++++++--- toolkit/xre/nsAppRunner.cpp | 10 +- toolkit/xre/nsUpdateDriver.cpp | 39 ++++ tools/update-packaging/common.sh | 62 ++++- tools/update-packaging/make_full_update.sh | 40 +++- tools/update-packaging/make_incremental_update.sh | 62 ++++- 24 files changed, 566 insertions(+), 123 deletions(-)
diff --git a/.mozconfig b/.mozconfig index e9a9432..97e0349 100755 --- a/.mozconfig +++ b/.mozconfig @@ -9,12 +9,15 @@ mk_add_options BUILD_OFFICIAL=1 ac_add_options --enable-optimize #ac_add_options --disable-optimize ac_add_options --enable-official-branding +ac_add_options --enable-tor-browser-update +ac_add_options --enable-update-packaging +# We do not use signed MAR files yet (Mozilla uses them on Windows only). +ac_add_options --disable-verify-mar ac_add_options --disable-strip ac_add_options --disable-install-strip ac_add_options --disable-tests ac_add_options --disable-debug ac_add_options --disable-maintenance-service -ac_add_options --disable-updater ac_add_options --disable-crashreporter ac_add_options --disable-webrtc #ac_add_options --disable-ctypes diff --git a/.mozconfig-mac b/.mozconfig-mac index 25a3f7d..7f28096 100644 --- a/.mozconfig-mac +++ b/.mozconfig-mac @@ -38,7 +38,11 @@ ac_add_options --disable-debug
# See above for a reason why this is currently disabled # ac_add_options --with-macos-private-frameworks=$CROSS_PRIVATE_FRAMEWORKS -ac_add_options --disable-updater +#ac_add_options --disable-updater +ac_add_options --enable-tor-browser-update +ac_add_options --enable-update-packaging +# We do not use signed MAR files yet (Mozilla uses them on Windows only). +ac_add_options --disable-verify-mar ac_add_options --disable-crashreporter ac_add_options --disable-maintenance-service ac_add_options --disable-webrtc diff --git a/.mozconfig-mingw b/.mozconfig-mingw index 78f9a06..9c8695d 100644 --- a/.mozconfig-mingw +++ b/.mozconfig-mingw @@ -14,8 +14,11 @@ ac_add_options --disable-debug ac_add_options --enable-optimize ac_add_options --enable-strip ac_add_options --enable-official-branding +ac_add_options --enable-tor-browser-update +ac_add_options --enable-update-packaging +# We do not use signed MAR files yet (Mozilla uses them on Windows only). +ac_add_options --disable-verify-mar
-ac_add_options --disable-updater ac_add_options --disable-crashreporter ac_add_options --disable-maintenance-service ac_add_options --disable-webrtc diff --git a/accessible/src/Makefile.in b/accessible/src/Makefile.in index aafeb3b..762a89c 100644 --- a/accessible/src/Makefile.in +++ b/accessible/src/Makefile.in @@ -13,7 +13,7 @@ A11Y_LOG = 0 ifdef MOZ_DEBUG A11Y_LOG = 1 endif -ifeq (,$(filter aurora beta release esr,$(MOZ_UPDATE_CHANNEL))) +ifeq (,$(filter aurora alpha beta release esr,$(MOZ_UPDATE_CHANNEL))) A11Y_LOG = 1 endif export A11Y_LOG diff --git a/accessible/src/shared.mozbuild b/accessible/src/shared.mozbuild index 839ef82..52e9804 100644 --- a/accessible/src/shared.mozbuild +++ b/accessible/src/shared.mozbuild @@ -8,5 +8,5 @@ a11y_log = 0 if CONFIG['MOZ_DEBUG']: a11y_log = 1
-if CONFIG['MOZ_UPDATE_CHANNEL'] not in ('aurora', 'beta', 'release', 'esr'): +if CONFIG['MOZ_UPDATE_CHANNEL'] not in ('aurora', 'alpha', 'beta', 'release', 'esr'): a11y_log = 1 diff --git a/browser/app/profile/000-tor-browser.js b/browser/app/profile/000-tor-browser.js index a6ff777..ef2a2a3 100644 --- a/browser/app/profile/000-tor-browser.js +++ b/browser/app/profile/000-tor-browser.js @@ -2,9 +2,8 @@ # Tor Browser Bundle # Do not edit this file.
-// Disable browser auto updaters and associated homepage notifications +// Disable browser automatic updates and associated homepage notifications pref("app.update.auto", false); -pref("app.update.enabled", false); pref("browser.search.update", false); pref("browser.rights.3.shown", true); pref("browser.startup.homepage_override.mstone", "ignore"); @@ -156,5 +155,6 @@ pref("media.audio_data.enabled", false); // https://trac.torproject.org/projects/tor/ticket/11253 pref("security.tls.version.max", 3);
-// Version placeholder -pref("torbrowser.version", "UNKNOWN"); +#ifdef TOR_BROWSER_VERSION +#expand pref("torbrowser.version", __TOR_BROWSER_VERSION__); +#endif diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index ae78798..3e3a77c 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -121,11 +121,8 @@ pref("app.update.cert.maxErrors", 5); // when the |app.update.cert.checkAttributes| preference is set to false. Also, // the |app.update.url.override| preference should ONLY be used for testing. // IMPORTANT! metro.js should also be updated for updates to certs.X.issuerName -pref("app.update.certs.1.issuerName", "CN=Thawte SSL CA,O="Thawte, Inc.",C=US"); -pref("app.update.certs.1.commonName", "aus3.mozilla.org"); - -pref("app.update.certs.2.issuerName", "CN=DigiCert Secure Server CA,O=DigiCert Inc,C=US"); -pref("app.update.certs.2.commonName", "aus3.mozilla.org"); +pref("app.update.certs.1.issuerName", "CN=DigiCert SHA2 High Assurance Server CA,OU=www.digicert.com,O=DigiCert Inc,C=US"); +pref("app.update.certs.1.commonName", "*.torproject.org");
// Whether or not app updates are enabled pref("app.update.enabled", true); @@ -155,7 +152,7 @@ pref("app.update.silent", false); pref("app.update.staging.enabled", true);
// Update service URL: -pref("app.update.url", "https://aus3.mozilla.org/update/3/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARG..."); +pref("app.update.url", "https://www.torproject.org/dist/torbrowser/update/%CHANNEL%/%BUILD_TARGET%/%..."); // app.update.url.manual is in branding section // app.update.url.details is in branding section
@@ -173,7 +170,7 @@ pref("app.update.idletime", 60); // upgrade start page instead! Other apps may wish to show this UI, and supply // a whatsNewURL field in their brand.properties that contains a link to a page // which tells users what's new in this new update. -pref("app.update.showInstalledUI", false); +pref("app.update.showInstalledUI", true);
// 0 = suppress prompting for incompatibilities if there are updates available // to newer versions of installed addons that resolve them. diff --git a/browser/base/content/aboutDialog.js b/browser/base/content/aboutDialog.js index ea8350c..c72c828 100644 --- a/browser/base/content/aboutDialog.js +++ b/browser/base/content/aboutDialog.js @@ -7,6 +7,11 @@ Components.utils.import("resource://gre/modules/Services.jsm");
const PREF_EM_HOTFIX_ID = "extensions.hotfix.id";
+#ifdef TOR_BROWSER_VERSION +# Add double-quotes back on (stripped by JarMaker.py). +#expand const TOR_BROWSER_VERSION = "__TOR_BROWSER_VERSION__"; +#endif + function init(aEvent) { if (aEvent.target != document) @@ -37,13 +42,16 @@ function init(aEvent) // Include the build ID and display warning if this is an "a#" (nightly or aurora) build let version = Services.appinfo.version; if (/a\d+$/.test(version)) { - let buildID = Services.appinfo.appBuildID; - let buildDate = buildID.slice(0,4) + "-" + buildID.slice(4,6) + "-" + buildID.slice(6,8); - document.getElementById("version").textContent += " (" + buildDate + ")"; document.getElementById("experimental").hidden = false; document.getElementById("communityDesc").hidden = true; }
+#ifdef TOR_BROWSER_VERSION + let versionElem = document.getElementById("version"); + if (versionElem) + versionElem.textContent += " (TBB " + TOR_BROWSER_VERSION + ")"; +#endif + #ifdef MOZ_UPDATER gAppUpdater = new appUpdater();
@@ -328,9 +336,15 @@ appUpdater.prototype = return; }
+ // If the update has the same version as the current application, + // skip add-on compatibility check and start downloading now. +#ifdef TOR_BROWSER_UPDATE + var pkgVersion = TOR_BROWSER_VERSION; +#else + var pkgVersion = Services.appinfo.version; +#endif if (!gAppUpdater.update.appVersion || - Services.vc.compare(gAppUpdater.update.appVersion, - Services.appinfo.version) == 0) { + Services.vc.compare(gAppUpdater.update.appVersion, pkgVersion) == 0) { gAppUpdater.startDownload(); return; } @@ -396,11 +410,16 @@ appUpdater.prototype = // (see bug 566787). The hotfix add-on is also ignored as it shouldn't // block the user from upgrading. try { +#ifdef TOR_BROWSER_UPDATE + let compatVersion = self.update.platformVersion; +#else + let compatVersion = self.update.appVersion; +#endif if (aAddon.type != "plugin" && aAddon.id != hotfixID && !aAddon.appDisabled && !aAddon.userDisabled && aAddon.scope != AddonManager.SCOPE_APPLICATION && aAddon.isCompatible && - !aAddon.isCompatibleWith(self.update.appVersion, + !aAddon.isCompatibleWith(compatVersion, self.update.platformVersion)) self.addons.push(aAddon); } @@ -424,8 +443,13 @@ appUpdater.prototype = */ checkAddonsForUpdates: function() { this.addons.forEach(function(aAddon) { +#ifdef TOR_BROWSER_UPDATE + let compatVersion = self.update.platformVersion; +#else + let compatVersion = self.update.appVersion; +#endif aAddon.findUpdates(this, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, - this.update.appVersion, + compatVersion, this.update.platformVersion); }, this); }, @@ -446,8 +470,13 @@ appUpdater.prototype = * See XPIProvider.jsm */ onUpdateAvailable: function(aAddon, aInstall) { +#ifdef TOR_BROWSER_UPDATE + let compatVersion = self.update.platformVersion; +#else + let compatVersion = self.update.appVersion; +#endif if (!Services.blocklist.isAddonBlocklisted(aAddon.id, aInstall.version, - this.update.appVersion, + compatVersion, this.update.platformVersion)) { // Compatibility or new version updates mean the same thing here. this.onCompatibilityUpdateAvailable(aAddon); diff --git a/browser/branding/official/pref/firefox-branding.js b/browser/branding/official/pref/firefox-branding.js index 0201301..6a15345 100644 --- a/browser/branding/official/pref/firefox-branding.js +++ b/browser/branding/official/pref/firefox-branding.js @@ -13,10 +13,10 @@ pref("app.update.download.backgroundInterval", 60); pref("app.update.promptWaitTime", 172800); // URL user can browse to manually if for some reason all update installation // attempts fail. -pref("app.update.url.manual", "https://www.mozilla.org/firefox/"); +pref("app.update.url.manual", "https://www.torproject.org/download/download-easy.html"); // A default value for the "More information about this update" link // supplied in the "An update is available" page of the update wizard. -pref("app.update.url.details", "https://www.mozilla.org/%LOCALE%/firefox/notes"); +pref("app.update.url.details", "https://www.torproject.org/projects/torbrowser.html");
pref("browser.search.param.ms-pc", "MOZI"); pref("browser.search.param.yahoo-fr", "moz35"); diff --git a/browser/confvars.sh b/browser/confvars.sh index 5bcb399..5432d51 100644 --- a/browser/confvars.sh +++ b/browser/confvars.sh @@ -8,21 +8,6 @@ MOZ_APP_VENDOR=Mozilla MOZ_UPDATER=1 MOZ_PHOENIX=1
-if test "$OS_ARCH" = "WINNT"; then - if ! test "$HAVE_64BIT_OS"; then - MOZ_VERIFY_MAR_SIGNATURE=1 - MOZ_MAINTENANCE_SERVICE=1 - if test "$MOZ_UPDATE_CHANNEL" = "nightly" -o \ - "$MOZ_UPDATE_CHANNEL" = "aurora" -o \ - "$MOZ_UPDATE_CHANNEL" = "beta" -o \ - "$MOZ_UPDATE_CHANNEL" = "release"; then - if ! test "$MOZ_DEBUG"; then - MOZ_STUB_INSTALLER=1 - fi - fi - fi -fi - MOZ_CHROME_FILE_FORMAT=omni MOZ_SAFE_BROWSING=1 MOZ_SERVICES_COMMON=1 @@ -46,9 +31,9 @@ MOZ_APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384} # This should usually be the same as the value MAR_CHANNEL_ID. # If more than one ID is needed, then you should use a comma separated list # of values. -ACCEPTED_MAR_CHANNEL_IDS=firefox-mozilla-esr +ACCEPTED_MAR_CHANNEL_IDS=torbrowser-torproject-release # The MAR_CHANNEL_ID must not contain the following 3 characters: ",\t " -MAR_CHANNEL_ID=firefox-mozilla-esr +MAR_CHANNEL_ID=torbrowser-torproject-release MOZ_PROFILE_MIGRATOR=1 MOZ_EXTENSION_MANAGER=1 MOZ_APP_STATIC_INI=1 diff --git a/browser/installer/Makefile.in b/browser/installer/Makefile.in index 4e3ab6f..b0700db 100644 --- a/browser/installer/Makefile.in +++ b/browser/installer/Makefile.in @@ -76,6 +76,10 @@ ifdef WIN32_REDIST_DIR DEFINES += -DMOZ_MSVC_REDIST=$(_MSC_VER) endif
+ifdef TOR_BROWSER_UPDATE +DEFINES += -DTOR_BROWSER_UPDATE +endif + ifneq (,$(filter WINNT Darwin Android,$(OS_TARGET))) DEFINES += -DMOZ_SHARED_MOZGLUE=1 endif diff --git a/browser/installer/removed-files.in b/browser/installer/removed-files.in index 6801f63..f2554ea 100644 --- a/browser/installer/removed-files.in +++ b/browser/installer/removed-files.in @@ -1434,7 +1434,9 @@ xpicleanup@BIN_SUFFIX@ #endif #if MOZ_MSVC_REDIST != 1600 msvcp100.dll - msvcr100.dll + #ifndef TOR_BROWSER_UPDATE + msvcr100.dll + #endif #endif #if MOZ_MSVC_REDIST != 1700 msvcp110.dll diff --git a/config/createprecomplete.py b/config/createprecomplete.py index 7fe8109..8332b21 100644 --- a/config/createprecomplete.py +++ b/config/createprecomplete.py @@ -5,6 +5,7 @@ # update instructions which is used to remove files and directories that are no # longer present in a complete update. The current working directory is used for # the location to enumerate and to create the precomplete file. +# For symlinks, remove instructions are always generated.
import sys import os @@ -12,7 +13,10 @@ import os def get_build_entries(root_path): """ Iterates through the root_path, creating a list for each file and directory. Excludes any path starting with extensions or distribution - and paths ending with channel-prefs.js. + and paths ending with channel-prefs.js. To support Tor Browser updates, + excludes TorBrowser/Data/Browser/profiles.ini, + TorBrowser/Data/Browser/profile.default/bookmarks.html and + TorBrowser/Data/Tor/torrc. """ rel_file_path_set = set() rel_dir_path_set = set() @@ -23,6 +27,9 @@ def get_build_entries(root_path): rel_path_file = rel_path_file.replace("\", "/") if not (rel_path_file.startswith("distribution/") or rel_path_file.startswith("extensions/") or + rel_path_file == "TorBrowser/Data/Browser/profiles.ini" or + rel_path_file == "TorBrowser/Data/Browser/profile.default/bookmarks.html" or + rel_path_file == "TorBrowser/Data/Tor/torrc" or rel_path_file.endswith("channel-prefs.js")): rel_file_path_set.add(rel_path_file)
@@ -32,7 +39,10 @@ def get_build_entries(root_path): rel_path_dir = rel_path_dir.replace("\", "/")+"/" if not (rel_path_dir.startswith("distribution/") or rel_path_dir.startswith("extensions/")): - rel_dir_path_set.add(rel_path_dir) + if (os.path.islink(rel_path_dir[:-1])): + rel_file_path_set.add(rel_path_dir[:-1]) + else: + rel_dir_path_set.add(rel_path_dir)
rel_file_path_list = list(rel_file_path_set) rel_file_path_list.sort(reverse=True) diff --git a/configure.in b/configure.in index 7de51e7..243aaee 100644 --- a/configure.in +++ b/configure.in @@ -3849,15 +3849,12 @@ AC_SUBST(GRE_MILESTONE) # set RELEASE_BUILD and NIGHTLY_BUILD variables depending on the cycle we're in # The logic works like this: # - if we have "a1" in GRE_MILESTONE, we're building Nightly (define NIGHTLY_BUILD) -# - otherwise, if we have "a" in GRE_MILESTONE, we're building Nightly or Aurora # - otherwise, we're building Release/Beta (define RELEASE_BUILD) case "$GRE_MILESTONE" in *a1*) NIGHTLY_BUILD=1 AC_DEFINE(NIGHTLY_BUILD) ;; - *a*) - ;; *) RELEASE_BUILD=1 AC_DEFINE(RELEASE_BUILD) @@ -6408,6 +6405,31 @@ MOZ_ARG_ENABLE_BOOL(update-packaging, AC_SUBST(MOZ_UPDATE_PACKAGING)
dnl ======================================================== +dnl Tor Additions +dnl ======================================================== +MOZ_ARG_WITH_STRING(tor-browser-version, +[ --with-tor-browser-version=VERSION + Set Tor Browser version, e.g., 4.0b1], + TOR_BROWSER_VERSION="$withval") + +MOZ_ARG_ENABLE_BOOL(tor-browser-update, +[ --enable-tor-browser-update + Enable Tor Browser update], + TOR_BROWSER_UPDATE=1, + TOR_BROWSER_UPDATE= ) + +if test -n "$TOR_BROWSER_UPDATE"; then + if test -z "$TOR_BROWSER_VERSION"; then + AC_MSG_ERROR([--enable-tor-browser-update requires --with-tor-browser-version.]) + fi + AC_DEFINE(TOR_BROWSER_UPDATE) +fi + +AC_DEFINE_UNQUOTED(TOR_BROWSER_VERSION,"$TOR_BROWSER_VERSION") +AC_SUBST(TOR_BROWSER_VERSION) +AC_SUBST(TOR_BROWSER_UPDATE) + +dnl ======================================================== dnl build the tests by default dnl ======================================================== MOZ_ARG_DISABLE_BOOL(tests, diff --git a/js/src/configure.in b/js/src/configure.in index 22ef8e2..e00c032 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -3074,15 +3074,12 @@ AC_SUBST(GRE_MILESTONE) dnl set RELEASE_BUILD and NIGHTLY_BUILD variables depending on the cycle we're in dnl The logic works like this: dnl - if we have "a1" in GRE_MILESTONE, we're building Nightly (define NIGHTLY_BUILD) -dnl - otherwise, if we have "a" in GRE_MILESTONE, we're building Nightly or Aurora dnl - otherwise, we're building Release/Beta (define RELEASE_BUILD) case "$GRE_MILESTONE" in *a1*) NIGHTLY_BUILD=1 AC_DEFINE(NIGHTLY_BUILD) ;; - *a*) - ;; *) RELEASE_BUILD=1 AC_DEFINE(RELEASE_BUILD) diff --git a/toolkit/modules/debug.js b/toolkit/modules/debug.js index 822ae90..4c20b82 100644 --- a/toolkit/modules/debug.js +++ b/toolkit/modules/debug.js @@ -40,6 +40,7 @@ this.NS_ASSERT = function NS_ASSERT(condition, message) { try { switch (defB.getCharPref("app.update.channel")) { case "nightly": + case "alpha": case "beta": case "default": releaseBuild = false; diff --git a/toolkit/mozapps/extensions/Makefile.in b/toolkit/mozapps/extensions/Makefile.in index ad9cc62..c90698d 100644 --- a/toolkit/mozapps/extensions/Makefile.in +++ b/toolkit/mozapps/extensions/Makefile.in @@ -9,7 +9,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
-ifeq (,$(filter aurora beta release esr,$(MOZ_UPDATE_CHANNEL))) +ifeq (,$(filter aurora alpha beta release esr,$(MOZ_UPDATE_CHANNEL))) DEFINES += -DMOZ_COMPATIBILITY_NIGHTLY=1 endif
diff --git a/toolkit/mozapps/update/nsUpdateService.js b/toolkit/mozapps/update/nsUpdateService.js index e7b6fa8..eb4a74a 100644 --- a/toolkit/mozapps/update/nsUpdateService.js +++ b/toolkit/mozapps/update/nsUpdateService.js @@ -11,7 +11,11 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); Components.utils.import("resource://gre/modules/FileUtils.jsm"); Components.utils.import("resource://gre/modules/AddonManager.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); +#ifdef BUILD_CTYPES +#ifdef XP_WIN Components.utils.import("resource://gre/modules/ctypes.jsm"); +#endif +#endif
const Cc = Components.classes; const Ci = Components.interfaces; @@ -73,6 +77,10 @@ const KEY_GRED = "GreD"; const KEY_UPDROOT = "UpdRootD"; const KEY_EXECUTABLE = "XREExeF";
+#ifdef TOR_BROWSER_VERSION +#expand const TOR_BROWSER_VERSION = __TOR_BROWSER_VERSION__; +#endif + #ifdef MOZ_WIDGET_GONK #define USE_UPDATE_ARCHIVE_DIR #endif @@ -253,6 +261,7 @@ XPCOMUtils.defineLazyGetter(this, "gOSVersion", function aus_gOSVersion() { }
if (osVersion) { +#ifdef BUILD_CTYPES #ifdef XP_WIN const BYTE = ctypes.uint8_t; const WORD = ctypes.uint16_t; @@ -359,6 +368,7 @@ XPCOMUtils.defineLazyGetter(this, "gOSVersion", function aus_gOSVersion() { } } #endif +#endif
try { osVersion += " (" + sysInfo.getProperty("secondaryLibrary") + ")"; @@ -1224,7 +1234,7 @@ function getLocale() { if (gLocale) return gLocale;
- for each (res in ['app', 'gre']) { + for each (var res in ['app', 'gre']) { var channel = Services.io.newChannel("resource://" + res + "/" + FILE_UPDATE_LOCALE, null, null); try { var inputStream = channel.open(); @@ -2390,9 +2400,14 @@ UpdateService.prototype = { updates.forEach(function(aUpdate) { // Ignore updates for older versions of the application and updates for // the same version of the application with the same build ID. - if (vc.compare(aUpdate.appVersion, Services.appinfo.version) < 0 || - vc.compare(aUpdate.appVersion, Services.appinfo.version) == 0 && - aUpdate.buildID == Services.appinfo.appBuildID) { +#ifdef TOR_BROWSER_UPDATE + var compatVersion = TOR_BROWSER_VERSION; +#else + var compatVersion = Services.appinfo.version; +#endif + var rc = vc.compare(aUpdate.appVersion, compatVersion); + if (rc < 0 || ((rc == 0) && + (aUpdate.buildID == Services.appinfo.appBuildID))) { LOG("UpdateService:selectUpdate - skipping update because the " + "update's application version is less than the current " + "application version"); @@ -2548,8 +2563,13 @@ UpdateService.prototype = { }
// Only check add-on compatibility when the version changes. +#ifdef TOR_BROWSER_UPDATE + var compatVersion = TOR_BROWSER_VERSION; +#else + var compatVersion = Services.appinfo.version; +#endif if (update.appVersion && - Services.vc.compare(update.appVersion, Services.appinfo.version) != 0) { + Services.vc.compare(update.appVersion, compatVersion) != 0) { this._update = update; this._checkAddonCompatibility(); } @@ -2577,6 +2597,11 @@ UpdateService.prototype = { // Get all the installed add-ons var self = this; AddonManager.getAllAddons(function(addons) { +#ifdef TOR_BROWSER_UPDATE + let compatVersion = self._update.platformVersion; +#else + let compatVersion = self._update.appVersion; +#endif self._incompatibleAddons = []; addons.forEach(function(addon) { // Protect against code that overrides the add-ons manager and doesn't @@ -2605,7 +2630,7 @@ UpdateService.prototype = { !addon.appDisabled && !addon.userDisabled && addon.scope != AddonManager.SCOPE_APPLICATION && addon.isCompatible && - !addon.isCompatibleWith(self._update.appVersion, + !addon.isCompatibleWith(compatVersion, self._update.platformVersion)) self._incompatibleAddons.push(addon); } @@ -2641,7 +2666,7 @@ UpdateService.prototype = {
self._incompatibleAddons.forEach(function(addon) { addon.findUpdates(this, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, - this._update.appVersion, this._update.platformVersion); + compatVersion, this._update.platformVersion); }, self); } else { @@ -2677,8 +2702,13 @@ UpdateService.prototype = { // the add-on will become incompatible. let bs = Cc["@mozilla.org/extensions/blocklist;1"]. getService(Ci.nsIBlocklistService); +#ifdef TOR_BROWSER_UPDATE + let compatVersion = gUpdates.update.platformVersion; +#else + let compatVersion = gUpdates.update.appVersion; +#endif if (bs.isAddonBlocklisted(addon.id, install.version, - gUpdates.update.appVersion, + compatVersion, gUpdates.update.platformVersion)) return;
@@ -2781,14 +2811,24 @@ UpdateService.prototype = { // current application's version or the update's version is the same as the // application's version and the build ID is the same as the application's // build ID. +#ifdef TOR_BROWSER_UPDATE + var compatVersion = TOR_BROWSER_VERSION; +#else + var compatVersion = Services.appinfo.version; +#endif if (update.appVersion && - (Services.vc.compare(update.appVersion, Services.appinfo.version) < 0 || + (Services.vc.compare(update.appVersion, compatVersion) < 0 || update.buildID && update.buildID == Services.appinfo.appBuildID && - update.appVersion == Services.appinfo.version)) { + update.appVersion == compatVersion)) { LOG("UpdateService:downloadUpdate - canceling download of update since " + "it is for an earlier or same application version and build ID.\n" + - "current application version: " + Services.appinfo.version + "\n" + +#ifdef TOR_BROWSER_UPDATE + "current Tor Browser version: " + compatVersion + "\n" + + "update Tor Browser version : " + update.appVersion + "\n" + +#else + "current application version: " + compatVersion + "\n" + "update application version : " + update.appVersion + "\n" + +#endif "current build ID: " + Services.appinfo.appBuildID + "\n" + "update build ID : " + update.buildID); cleanupActiveUpdate(); @@ -2821,7 +2861,7 @@ UpdateService.prototype = { } #endif // Set the previous application version prior to downloading the update. - update.previousAppVersion = Services.appinfo.version; + update.previousAppVersion = compatVersion; this._downloader = new Downloader(background, this); return this._downloader.downloadUpdate(update); }, @@ -3233,7 +3273,11 @@ Checker.prototype = { }
url = url.replace(/%PRODUCT%/g, Services.appinfo.name); +#ifdef TOR_BROWSER_UPDATE + url = url.replace(/%VERSION%/g, TOR_BROWSER_VERSION); +#else url = url.replace(/%VERSION%/g, Services.appinfo.version); +#endif url = url.replace(/%BUILD_ID%/g, Services.appinfo.appBuildID); url = url.replace(/%BUILD_TARGET%/g, Services.appinfo.OS + "_" + gABI); url = url.replace(/%OS_VERSION%/g, gOSVersion); diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp index 4012f00..7a5220d 100644 --- a/toolkit/mozapps/update/updater/updater.cpp +++ b/toolkit/mozapps/update/updater/updater.cpp @@ -20,7 +20,7 @@ * updatev2.manifest * ----------------- * method = "add" | "add-if" | "patch" | "patch-if" | "remove" | - * "rmdir" | "rmrfdir" | type + * "rmdir" | "rmrfdir" | "addsymlink" | type * * 'type' is the update type (e.g. complete or partial) and when present MUST * be the first entry in the update manifest. The type is used to support @@ -404,10 +404,12 @@ get_full_path(const NS_tchar *relpath) * The line from the manifest that contains the path. * @param isdir * Whether the path is a directory path. Defaults to false. + * @param islinktarget + * Whether the path is a symbolic link target. Defaults to false. * @return valid filesystem path or NULL if the path checks fail. */ static NS_tchar* -get_valid_path(NS_tchar **line, bool isdir = false) +get_valid_path(NS_tchar **line, bool isdir = false, bool islinktarget = false) { NS_tchar *path = mstrtok(kQuote, line); if (!path) { @@ -442,10 +444,12 @@ get_valid_path(NS_tchar **line, bool isdir = false) path[NS_tstrlen(path) - 1] = NS_T('\0'); }
- // Don't allow relative paths that resolve to a parent directory. - if (NS_tstrstr(path, NS_T("..")) != NULL) { - LOG(("get_valid_path: paths must not contain '..': " LOG_S, path)); - return NULL; + if (!islinktarget) { + // Don't allow relative paths that resolve to a parent directory. + if (NS_tstrstr(path, NS_T("..")) != NULL) { + LOG(("get_valid_path: paths must not contain '..': " LOG_S, path)); + return NULL; + } }
return path; @@ -480,7 +484,8 @@ static void ensure_write_permissions(const NS_tchar *path) (void) _wchmod(path, _S_IREAD | _S_IWRITE); #else struct stat fs; - if (!stat(path, &fs) && !(fs.st_mode & S_IWUSR)) { + if (!NS_tlstat(path, &fs) && !S_ISLNK(fs.st_mode) + && !(fs.st_mode & S_IWUSR)) { (void)chmod(path, fs.st_mode | S_IWUSR); } #endif @@ -680,7 +685,7 @@ static int ensure_copy(const NS_tchar *path, const NS_tchar *dest) return READ_ERROR; }
-#ifdef XP_UNIX +#ifndef XP_WIN if (S_ISLNK(ss.st_mode)) { return ensure_copy_symlink(path, dest); } @@ -779,7 +784,7 @@ static int ensure_copy_recursive(const NS_tchar *path, const NS_tchar *dest, return READ_ERROR; }
-#ifdef XP_UNIX +#ifndef XP_WIN if (S_ISLNK(sInfo.st_mode)) { return ensure_copy_symlink(path, dest); } @@ -838,14 +843,19 @@ static int rename_file(const NS_tchar *spath, const NS_tchar *dpath, return rv;
struct stat spathInfo; - rv = NS_tstat(spath, &spathInfo); + rv = NS_tlstat(spath, &spathInfo); if (rv) { LOG(("rename_file: failed to read file status info: " LOG_S ", " \ "err: %d", spath, errno)); return READ_ERROR; }
- if (!S_ISREG(spathInfo.st_mode)) { +#ifdef XP_WIN + if (!S_ISREG(spathInfo.st_mode)) +#else + if (!S_ISREG(spathInfo.st_mode) && !S_ISLNK(spathInfo.st_mode)) +#endif + { if (allowDirs && !S_ISDIR(spathInfo.st_mode)) { LOG(("rename_file: path present, but not a file: " LOG_S ", err: %d", spath, errno)); @@ -855,7 +865,12 @@ static int rename_file(const NS_tchar *spath, const NS_tchar *dpath, } }
- if (!NS_taccess(dpath, F_OK)) { +#ifdef XP_WIN + if (!NS_taccess(dpath, F_OK)) +#else + if (!S_ISLNK(spathInfo.st_mode) && !NS_taccess(dpath, F_OK)) +#endif + { if (ensure_remove(dpath)) { LOG(("rename_file: destination file exists and could not be " \ "removed: " LOG_S, dpath)); @@ -892,7 +907,18 @@ static int backup_restore(const NS_tchar *path) NS_tsnprintf(backup, sizeof(backup)/sizeof(backup[0]), NS_T("%s") BACKUP_EXT, path);
- if (NS_taccess(backup, F_OK)) { + bool isLink = false; +#ifndef XP_WIN + struct stat linkInfo; + int rv = NS_tlstat(path, &linkInfo); + if (!rv) { + LOG(("backup_restore: cannot get info for backup file: " LOG_S, backup)); + return OK; + } + isLink = S_ISLNK(linkInfo.st_mode); +#endif + + if (!isLink && NS_taccess(backup, F_OK)) { LOG(("backup_restore: backup file doesn't exist: " LOG_S, backup)); return OK; } @@ -907,8 +933,18 @@ static int backup_discard(const NS_tchar *path) NS_tsnprintf(backup, sizeof(backup)/sizeof(backup[0]), NS_T("%s") BACKUP_EXT, path);
+ bool isLink = false; +#ifndef XP_WIN + struct stat linkInfo; + int rv2 = NS_tlstat(backup, &linkInfo); + if (rv2) { + return OK; // File does not exist; nothing to do. + } + isLink = S_ISLNK(linkInfo.st_mode); +#endif + // Nothing to discard - if (NS_taccess(backup, F_OK)) { + if (!isLink && NS_taccess(backup, F_OK)) { return OK; }
@@ -988,7 +1024,7 @@ private: class RemoveFile : public Action { public: - RemoveFile() : mFile(NULL), mSkip(0) { } + RemoveFile() : mFile(NULL), mSkip(0), mIsLink(0) { }
int Parse(NS_tchar *line); int Prepare(); @@ -998,6 +1034,7 @@ public: private: const NS_tchar *mFile; int mSkip; + int mIsLink; };
int @@ -1015,28 +1052,39 @@ RemoveFile::Parse(NS_tchar *line) int RemoveFile::Prepare() { - // Skip the file if it already doesn't exist. - int rv = NS_taccess(mFile, F_OK); - if (rv) { - mSkip = 1; - mProgressCost = 0; - return OK; + int rv; +#ifndef XP_WIN + struct stat linkInfo; + rv = NS_tlstat(mFile, &linkInfo); + mIsLink = ((0 == rv) && S_ISLNK(linkInfo.st_mode)); +#endif + + if (!mIsLink) { + // Skip the file if it already doesn't exist. + rv = NS_taccess(mFile, F_OK); + if (rv) { + mSkip = 1; + mProgressCost = 0; + return OK; + } }
LOG(("PREPARE REMOVEFILE " LOG_S, mFile));
- // Make sure that we're actually a file... - struct stat fileInfo; - rv = NS_tstat(mFile, &fileInfo); - if (rv) { - LOG(("failed to read file status info: " LOG_S ", err: %d", mFile, - errno)); - return READ_ERROR; - } + if (!mIsLink) { + // Make sure that we're actually a file... + struct stat fileInfo; + rv = NS_tstat(mFile, &fileInfo); + if (rv) { + LOG(("failed to read file status info: " LOG_S ", err: %d", mFile, + errno)); + return READ_ERROR; + }
- if (!S_ISREG(fileInfo.st_mode)) { - LOG(("path present, but not a file: " LOG_S, mFile)); - return UNEXPECTED_FILE_OPERATION_ERROR; + if (!S_ISREG(fileInfo.st_mode)) { + LOG(("path present, but not a file: " LOG_S, mFile)); + return UNEXPECTED_FILE_OPERATION_ERROR; + } }
NS_tchar *slash = (NS_tchar *) NS_tstrrchr(mFile, NS_T('/')); @@ -1066,7 +1114,13 @@ RemoveFile::Execute()
// The file is checked for existence here and in Prepare since it might have // been removed by a separate instruction: bug 311099. - int rv = NS_taccess(mFile, F_OK); + int rv = 0; + if (mIsLink) { + struct stat linkInfo; + rv = NS_tlstat(mFile, &linkInfo); + } else { + rv = NS_taccess(mFile, F_OK); + } if (rv) { LOG(("file cannot be removed because it does not exist; skipping")); mSkip = 1; @@ -1683,6 +1737,97 @@ PatchIfFile::Finish(int status) PatchFile::Finish(status); }
+#ifndef XP_WIN +class AddSymlink : public Action +{ +public: + AddSymlink() : mLinkName(NULL) + , mTarget(NULL) + , mAdded(false) + { } + + virtual int Parse(NS_tchar *line); + virtual int Prepare(); + virtual int Execute(); + virtual void Finish(int status); + +private: + const NS_tchar *mLinkName; + const NS_tchar *mTarget; + bool mAdded; +}; + +int +AddSymlink::Parse(NS_tchar *line) +{ + // format "<linkname>" "target" + + mLinkName = get_valid_path(&line); + if (!mLinkName) + return PARSE_ERROR; + + // consume whitespace between args + NS_tchar *q = mstrtok(kQuote, &line); + if (!q) + return PARSE_ERROR; + + mTarget = get_valid_path(&line, false, true); + if (!mTarget) + return PARSE_ERROR; + + return OK; +} + +int +AddSymlink::Prepare() +{ + LOG(("PREPARE ADDSYMLINK " LOG_S " -> " LOG_S, mLinkName, mTarget)); + + return OK; +} + +int +AddSymlink::Execute() +{ + LOG(("EXECUTE ADDSYMLINK " LOG_S " -> " LOG_S, mLinkName, mTarget)); + + // First make sure that we can actually get rid of any existing file or link. + struct stat linkInfo; + int rv = NS_tlstat(mLinkName, &linkInfo); + if ((0 == rv) && !S_ISLNK(linkInfo.st_mode)) { + rv = NS_taccess(mLinkName, F_OK); + } + if (rv == 0) { + rv = backup_create(mLinkName); + if (rv) + return rv; + } else { + rv = ensure_parent_dir(mLinkName); + if (rv) + return rv; + } + + // Create the link. + rv = symlink(mTarget, mLinkName); + if (!rv) { + mAdded = true; + } + + return rv; +} + +void +AddSymlink::Finish(int status) +{ + LOG(("FINISH ADDSYMLINK " LOG_S " -> " LOG_S, mLinkName, mTarget)); + // When there is an update failure and a link has been added it is removed + // here since there might not be a backup to replace it. + if (status && mAdded) + NS_tremove(mLinkName); + backup_finish(mLinkName, status); +} +#endif + //-----------------------------------------------------------------------------
#ifdef XP_WIN @@ -1902,19 +2047,40 @@ CopyInstallDirToDestDir()
// These files should not be copied over to the updated app #ifdef XP_WIN -#define SKIPLIST_COUNT 3 + #ifdef TOR_BROWSER_UPDATE + #define SKIPLIST_COUNT 5 + #else + #define SKIPLIST_COUNT 3 + #endif #else -#define SKIPLIST_COUNT 2 + #ifdef TOR_BROWSER_UPDATE + #define SKIPLIST_COUNT 4 + #else + #define SKIPLIST_COUNT 2 + #endif #endif copy_recursive_skiplist<SKIPLIST_COUNT> skiplist; #ifdef XP_MACOSX skiplist.append(0, installDir, NS_T("Updated.app")); skiplist.append(1, installDir, NS_T("Contents/MacOS/updates/0")); +#ifdef TOR_BROWSER_UPDATE + skiplist.append(2, installDir, NS_T("TorBrowser/Data/Browser/profile.default/.parentlock")); + skiplist.append(3, installDir, NS_T("TorBrowser/Data/Tor/lock")); +#endif #else skiplist.append(0, installDir, NS_T("updated")); skiplist.append(1, installDir, NS_T("updates/0")); +#ifdef TOR_BROWSER_UPDATE +#ifdef XP_UNIX + skiplist.append(2, installDir, NS_T("TorBrowser/Data/Browser/profile.default/.parentlock")); +#else + skiplist.append(2, installDir, NS_T("TorBrowser/Data/Browser/profile.default/parent.lock")); +#endif + skiplist.append(3, installDir, NS_T("TorBrowser/Data/Tor/lock")); +#endif #ifdef XP_WIN - skiplist.append(2, installDir, NS_T("updated.update_in_progress.lock")); + skiplist.append(SKIPLIST_COUNT - 1, installDir, + NS_T("updated.update_in_progress.lock")); #endif #endif
@@ -3124,7 +3290,7 @@ int NS_main(int argc, NS_tchar **argv) LogFinish();
if (argc > callbackIndex) { -#if defined(XP_WIN) +#if defined(XP_WIN) && !defined(TOR_BROWSER_UPDATE) if (gSucceeded) { // The service update will only be executed if it is already installed. // For first time installs of the service, the install will happen from @@ -3747,6 +3913,11 @@ int DoUpdate() else if (NS_tstrcmp(token, NS_T("add-cc")) == 0) { // no longer supported continue; } +#ifndef XP_WIN + else if (NS_tstrcmp(token, NS_T("addsymlink")) == 0) { + action = new AddSymlink(); + } +#endif else { LOG(("DoUpdate: unknown token: " LOG_S, token)); return PARSE_ERROR; diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 42787c0..c94839f 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -3499,12 +3499,20 @@ XREMain::XRE_mainStartup(bool* aExitFlag) NS_ENSURE_SUCCESS(rv, 1); rv = exeFile->GetParent(getter_AddRefs(exeDir)); NS_ENSURE_SUCCESS(rv, 1); +#ifdef TOR_BROWSER_UPDATE + nsAutoCString compatVersion(TOR_BROWSER_VERSION); +#endif ProcessUpdates(mDirProvider.GetGREDir(), exeDir, updRoot, gRestartArgc, gRestartArgv, - mAppData->version); +#ifdef TOR_BROWSER_UPDATE + compatVersion.get() +#else + mAppData->version +#endif + ); if (EnvHasValue("MOZ_PROCESS_UPDATES")) { SaveToEnv("MOZ_PROCESS_UPDATES="); *aExitFlag = true; diff --git a/toolkit/xre/nsUpdateDriver.cpp b/toolkit/xre/nsUpdateDriver.cpp index 5223e8cc8..a4e4034 100644 --- a/toolkit/xre/nsUpdateDriver.cpp +++ b/toolkit/xre/nsUpdateDriver.cpp @@ -139,6 +139,18 @@ GetCurrentWorkingDir(char *buf, size_t size) return NS_OK; }
+ +#ifdef DEBUG +static void +dump_argv(const char *aPrefix, char **argv, int argc) +{ + printf("%s - %d args\n", aPrefix, argc); + for (int i = 0; i < argc; ++i) + printf(" %d: %s\n", i, argv[i]); +} +#endif + + #if defined(XP_MACOSX) // This is a copy of OS X's XRE_GetBinaryPath from nsAppRunner.cpp with the // gBinaryPath check removed so that the updater can reload the stub executable @@ -294,6 +306,10 @@ IsOlderVersion(nsIFile *versionFile, const char *appVersion) if (strncmp(buf, kNull, sizeof(kNull) - 1) == 0) return false;
+#ifdef DEBUG + printf("IsOlderVersion checking appVersion %s against updateVersion %s\n", + appVersion, buf); +#endif if (mozilla::Version(appVersion) > buf) return true;
@@ -874,6 +890,9 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile, #endif
LOG(("spawning updater process [%s]\n", updaterPath.get())); +#ifdef DEBUG + dump_argv("ApplyUpdate updater", argv, argc); +#endif
#if defined(USE_EXECV) // Don't use execv for background updates. @@ -897,6 +916,9 @@ ApplyUpdate(nsIFile *greDir, nsIFile *updateDir, nsIFile *statusFile, // LaunchChildMac uses posix_spawnp and prefers the current // architecture when launching. It doesn't require a // null-terminated string but it doesn't matter if we pass one. +#ifdef DEBUG + dump_argv("ApplyUpdate after SetupMacCommandLine", argv, argc); +#endif LaunchChildMac(argc, argv, 0, outpid); if (restart) { exit(0); @@ -938,6 +960,12 @@ ProcessUpdates(nsIFile *greDir, nsIFile *appDir, nsIFile *updRootDir, nsresult rv;
nsCOMPtr<nsIFile> updatesDir; +#ifdef DEBUG + nsAutoCString path; + updRootDir->GetNativePath(path); + printf("ProcessUpdates updateRootDir: %s appVersion: %s\n", + path.get(), appVersion); +#endif rv = updRootDir->Clone(getter_AddRefs(updatesDir)); if (NS_FAILED(rv)) return rv; @@ -985,6 +1013,11 @@ ProcessUpdates(nsIFile *greDir, nsIFile *appDir, nsIFile *updRootDir,
nsCOMPtr<nsIFile> statusFile; UpdateStatus status = GetUpdateStatus(updatesDir, statusFile); +#ifdef DEBUG + printf("ProcessUpdates status: %d\n", status); + updatesDir->GetNativePath(path); + printf("ProcessUpdates updatesDir: %s\n", path.get()); +#endif switch (status) { case ePendingUpdate: case ePendingService: { @@ -1064,7 +1097,11 @@ nsUpdateProcessor::ProcessUpdate(nsIUpdate* aUpdate) if (NS_FAILED(rv)) appDir = dirProvider->GetAppDir();
+#ifdef TOR_BROWSER_UPDATE + appVersion = TOR_BROWSER_VERSION; +#else appVersion = gAppData->version; +#endif argc = gRestartArgc; argv = gRestartArgv; } else { @@ -1088,6 +1125,8 @@ nsUpdateProcessor::ProcessUpdate(nsIUpdate* aUpdate) if (NS_FAILED(rv)) updRoot = appDir;
+ // To support Tor Browser Bundle updates from xpcshell, modify the + // following code to use the TBB version fron the configure process. nsCOMPtr<nsIXULAppInfo> appInfo = do_GetService("@mozilla.org/xre/app-info;1"); if (appInfo) { diff --git a/tools/update-packaging/common.sh b/tools/update-packaging/common.sh index c358846..075ab08 100755 --- a/tools/update-packaging/common.sh +++ b/tools/update-packaging/common.sh @@ -9,6 +9,8 @@ #
# ----------------------------------------------------------------------------- +QUIET=0 + # By default just assume that these tools exist on our path MAR=${MAR:-mar} BZIP2=${BZIP2:-bzip2} @@ -21,6 +23,12 @@ notice() { echo "$*" 1>&2 }
+verbose_notice() { + if [ $QUIET -eq 0 ]; then + notice "$*" + fi +} + get_file_size() { info=($(ls -ln "$1")) echo ${info[4]} @@ -52,14 +60,22 @@ make_add_instruction() { # Use the subdirectory of the extensions folder as the file to test # before performing this add instruction. testdir=$(echo "$f" | sed 's/(.*distribution/extensions/[^/]*)/.*/\1/') - notice " add-if: $f$forced" + verbose_notice " add-if: $f$forced" echo "add-if "$testdir" "$f"" else - notice " add: $f$forced" + verbose_notice " add: $f$forced" echo "add "$f"" fi }
+make_addsymlink_instruction() { + link="$1" + target="$2" + + verbose_notice " addsymlink: $link -> $target" + echo "addsymlink "$link" "$target"" +} + make_patch_instruction() { f="$1" is_extension=$(echo "$f" | grep -c 'distribution/extensions/.*/') @@ -67,10 +83,10 @@ make_patch_instruction() { # Use the subdirectory of the extensions folder as the file to test # before performing this add instruction. testdir=$(echo "$f" | sed 's/(.*distribution/extensions/[^/]*)/.*/\1/') - notice " patch-if: $f" + verbose_notice " patch-if: $f" echo "patch-if "$testdir" "$f.patch" "$f"" else - notice " patch: $f" + verbose_notice " patch: $f" echo "patch "$f.patch" "$f"" fi } @@ -113,17 +129,17 @@ append_remove_instructions() { fi fi if [ $(echo "$f" | grep -c '/$') = 1 ]; then - notice " rmdir: $fixedprefix$f" - echo "rmdir "$fixedprefix$f"" >> $filev2 + verbose_notice " rmdir: $fixedprefix$f" + echo "rmdir "$fixedprefix$f"" >> "$filev2" elif [ $(echo "$f" | grep -c '/*$') = 1 ]; then # Remove the * f=$(echo "$f" | sed -e 's:*$::') - notice " rmrfdir: $fixedprefix$f" - echo "rmrfdir "$fixedprefix$f"" >> $filev2 + verbose_notice " rmrfdir: $fixedprefix$f" + echo "rmrfdir "$fixedprefix$f"" >> "$filev2" else - notice " remove: $fixedprefix$f" - echo "remove "$fixedprefix$f"" >> $filev1 - echo "remove "$fixedprefix$f"" >> $filev2 + verbose_notice " remove: $fixedprefix$f" + echo "remove "$fixedprefix$f"" >> "$filev1" + echo "remove "$fixedprefix$f"" >> "$filev2" fi fi fi @@ -132,6 +148,9 @@ append_remove_instructions() { }
# List all files in the current directory, stripping leading "./" +# To support Tor Browser updates, skip TorBrowser/Data/Browser/profiles.ini, +# TorBrowser/Data/Browser/profile.default/bookmarks.html and +# TorBrowser/Data/Tor/torrc. # Skip the channel-prefs.js file as it should not be included in any # generated MAR files (see bug 306077). Pass a variable name and it will be # filled as an array. @@ -147,6 +166,11 @@ list_files() { | sed 's/./(.*)/\1/' \ | sort -r > "temp-filelist" while read file; do + if [ $file = "TorBrowser/Data/Browser/profiles.ini" -o \ + $file = "TorBrowser/Data/Browser/profile.default/bookmarks.html" -o \ + $file = "TorBrowser/Data/Tor/torrc" ]; then + continue; + fi eval "${1}[$count]="$file"" (( count++ )) done < "temp-filelist" @@ -168,3 +192,19 @@ list_dirs() { done < "temp-dirlist" rm "temp-dirlist" } + +# List all symbolic links in the current directory, stripping leading "./" +list_symlinks() { + count=0 + + find . -type l \ + | sed 's/./(.*)/\1/' \ + | sort -r > "temp-symlinklist" + while read symlink; do + target=$(readlink "$symlink") + eval "${1}[$count]="$symlink"" + eval "${2}[$count]="$target"" + (( count++ )) + done < "temp-symlinklist" + rm "temp-symlinklist" +} diff --git a/tools/update-packaging/make_full_update.sh b/tools/update-packaging/make_full_update.sh index 03ba9af..b1ba54e 100755 --- a/tools/update-packaging/make_full_update.sh +++ b/tools/update-packaging/make_full_update.sh @@ -10,6 +10,9 @@
. $(dirname "$0")/common.sh
+# TODO: it would be better to pass this as a command line option. +directories_to_remove='TorBrowser/Data/Browser/profile.default/extensions/https-everywhere@eff.org' + # -----------------------------------------------------------------------------
print_usage() { @@ -28,10 +31,16 @@ if [ $1 = -h ]; then notice "" notice "Options:" notice " -h show this help text" + notice " -q be less verbose" notice "" exit 1 fi
+if [ $1 = -q ]; then + QUIET=1 + shift +fi + # -----------------------------------------------------------------------------
archive="$1" @@ -64,19 +73,20 @@ if [ ! -f "precomplete" ]; then fi
list_files files +list_symlinks symlinks symlink_targets
popd
notice "" notice "Adding file add instructions to file 'update.manifest'" -> $updatemanifestv1 +> "$updatemanifestv1"
num_files=${#files[*]}
for ((i=0; $i<$num_files; i=$i+1)); do f="${files[$i]}"
- make_add_instruction "$f" >> $updatemanifestv1 + make_add_instruction "$f" >> "$updatemanifestv1"
dir=$(dirname "$f") mkdir -p "$workdir/$dir" @@ -88,15 +98,35 @@ done
# Add the type of update to the beginning of and cat the contents of the version # 1 update manifest to the version 2 update manifest. -> $updatemanifestv2 +> "$updatemanifestv2" notice "" notice "Adding type instruction to file 'updatev2.manifest'" notice " type: complete" -echo "type "complete"" >> $updatemanifestv2 +echo "type "complete"" >> "$updatemanifestv2" + +# If removal of any old, existing directories is desired, emit the appropriate +# rmdfdir commands. +for dir_to_remove in $directories_to_remove; do + # rmrfdir requires a trailing slash; if slash is missing, add one. + if ! [[ "$dir_to_remove" =~ /$ ]]; then + dir_to_remove="${dir_to_remove}/" + fi + echo "rmrfdir "$dir_to_remove"" >> "$updatemanifestv2" +done +
notice "" notice "Concatenating file 'update.manifest' to file 'updatev2.manifest'" -cat $updatemanifestv1 >> $updatemanifestv2 +cat "$updatemanifestv1" >> "$updatemanifestv2" + +notice "" +notice "Adding symlink add instructions to file 'updatev2.manifest'" +num_symlinks=${#symlinks[*]} +for ((i=0; $i<$num_symlinks; i=$i+1)); do + link="${symlinks[$i]}" + target="${symlink_targets[$i]}" + make_addsymlink_instruction "$link" "$target" >> "$updatemanifestv2" +done
# Append remove instructions for any dead files. notice "" diff --git a/tools/update-packaging/make_incremental_update.sh b/tools/update-packaging/make_incremental_update.sh index 0363831..b58e7dd 100755 --- a/tools/update-packaging/make_incremental_update.sh +++ b/tools/update-packaging/make_incremental_update.sh @@ -21,6 +21,7 @@ print_usage() { notice " -h show this help text" notice " -f clobber this file in the installation" notice " Must be a path to a file to clobber in the partial update." + notice " -q be less verbose" notice "" }
@@ -47,6 +48,17 @@ check_for_forced_update() { ## "true" *giggle* return 0; fi + + # If the file in the skip list ends with /*, do a prefix match. + # This allows TorBrowser/Data/Browser/profile.default/extensions/https-everywhere@eff.org/* to be used to force all HTTPS Everywhere files to be updated. + f_suffix=${f##*/} + if [[ $f_suffix = "*" ]]; then + f_prefix="${f%/*}"; + if [[ $forced_file_chk == $f_prefix* ]]; then + ## 0 means "true" + return 0; + fi + fi done ## 'false'... because this is bash. Oh yay! return 1; @@ -57,13 +69,26 @@ if [ $# = 0 ]; then exit 1 fi
-requested_forced_updates='Contents/MacOS/firefox' +# The last .xpi is NoScript. +ext_path='TorBrowser/Data/Browser/profile.default/extensions'; +# TODO: it would be better to pass this as a command line option. +exts='https-everywhere@eff.org/* tor-launcher@torproject.org.xpi torbutton@torproject.org.xpi uriloader@pdf.js.xpi {73a6fe31-595d-460b-a920-fcc0f8843232}.xpi' +requested_forced_updates='Contents/MacOS/TorBrowser.app/Contents/MacOS/firefox' +for ext in $exts; do + requested_forced_updates="$requested_forced_updates $ext_path/$ext" +done + + +# TODO: it would be better to pass this as a command line option. +directories_to_remove='TorBrowser/Data/Browser/profile.default/extensions/https-everywhere@eff.org'
-while getopts "hf:" flag +while getopts "hqf:" flag do case "$flag" in h) print_usage; exit 0 ;; + q) QUIET=1 + ;; f) requested_forced_updates="$requested_forced_updates $OPTARG" ;; ?) print_usage; exit 1 @@ -102,6 +127,7 @@ if test $? -ne 0 ; then fi
list_files oldfiles +list_symlinks oldsymlinks oldsymlink_targets list_dirs olddirs
popd @@ -118,6 +144,7 @@ fi
list_dirs newdirs list_files newfiles +list_symlinks newsymlinks newsymlink_targets
popd
@@ -139,7 +166,7 @@ for ((i=0; $i<$num_oldfiles; i=$i+1)); do
# removed-files is excluded by make_incremental_updates.py so it is excluded # here for consistency. - if [ `basename $f` = "removed-files" ]; then + if [ "`basename "$f"`" = "removed-files" ]; then continue 1 fi
@@ -188,6 +215,23 @@ for ((i=0; $i<$num_oldfiles; i=$i+1)); do fi done
+# Remove and re-add symlinks +notice "" +notice "Adding symlink remove/add instructions to file 'update.manifest'" +num_oldsymlinks=${#oldsymlinks[*]} +for ((i=0; $i<$num_oldsymlinks; i=$i+1)); do + link="${oldsymlinks[$i]}" + verbose_notice " remove: $link" + echo "remove "$link"" >> $updatemanifestv1 +done + +num_newsymlinks=${#newsymlinks[*]} +for ((i=0; $i<$num_newsymlinks; i=$i+1)); do + link="${newsymlinks[$i]}" + target="${newsymlink_targets[$i]}" + make_addsymlink_instruction "$link" "$target" >> $updatemanifestv1 +done + # Newly added files notice "" notice "Adding file add instructions to file 'update.manifest'" @@ -198,7 +242,7 @@ for ((i=0; $i<$num_newfiles; i=$i+1)); do
# removed-files is excluded by make_incremental_updates.py so it is excluded # here for consistency. - if [ `basename $f` = "removed-files" ]; then + if [ "`basename "$f"`" = "removed-files" ]; then continue 1 fi
@@ -235,6 +279,16 @@ notice "Adding type instruction to file 'updatev2.manifest'" notice " type: partial" echo "type "partial"" >> $updatemanifestv2
+# If removal of any old, existing directories is desired, emit the appropriate +# rmdfdir commands. +for dir_to_remove in $directories_to_remove; do + # rmrfdir reuires a trailing slash, so add one if missing. + if ! [[ "$dir_to_remove" =~ /$ ]]; then + dir_to_remove="${dir_to_remove}/" + fi + echo "rmrfdir "$dir_to_remove"" >> $updatemanifestv2 +done + notice "" notice "Concatenating file 'update.manifest' to file 'updatev2.manifest'" cat $updatemanifestv1 >> $updatemanifestv2
tor-commits@lists.torproject.org