[tbb-commits] [tor-browser/tor-browser-24.7.0esr-4.x-2] Bug 4234: Use the Firefox Update Process for TBB.
mikeperry at torproject.org
mikeperry at torproject.org
Thu Aug 28 06:45:33 UTC 2014
commit 43c5ec54ce50cd08ccc27b02ef2b3ebbef9a02aa
Author: Kathy Brade <brade at 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_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
+pref("app.update.url", "https://www.torproject.org/dist/torbrowser/update/%CHANNEL%/%BUILD_TARGET%/%OS_VERSION%/%VERSION%/%LOCALE%");
// 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 at 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 at 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 at 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 at eff.org/* tor-launcher at torproject.org.xpi torbutton at torproject.org.xpi uriloader at 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 at 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
More information about the tbb-commits
mailing list