mirror of
https://github.com/zotero/zotero.git
synced 2026-08-28 05:25:31 +00:00
XULButtonElement only opens a type=menu button's menu when the button is the event's original target, which worked before because xul.css gave .toolbarbutton-menu-dropmarker 'pointer-events: none'. That rule was removed along with the dropmarker element, so clicks on our recreated dropmarker did nothing.
820 lines
38 KiB
Bash
Executable file
820 lines
38 KiB
Bash
Executable file
#!/bin/bash
|
||
set -euo pipefail
|
||
|
||
# Copyright (c) 2011 Zotero
|
||
# Center for History and New Media
|
||
# George Mason University, Fairfax, Virginia, USA
|
||
# http://zotero.org
|
||
#
|
||
# This program is free software: you can redistribute it and/or modify
|
||
# it under the terms of the GNU General Public License as published by
|
||
# the Free Software Foundation, either version 3 of the License, or
|
||
# (at your option) any later version.
|
||
#
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
#
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||
. "$APP_ROOT_DIR/config.sh"
|
||
. "$SCRIPT_DIR/utils.sh"
|
||
cd "$APP_ROOT_DIR"
|
||
|
||
usage() {
|
||
cat >&2 <<'DONE'
|
||
Usage: fetch_xulrunner.sh -p <m|w|l> [-a ARCH]
|
||
|
||
Required
|
||
-p PLATFORM m (Mac), w (Windows), l (Linux)
|
||
|
||
Optional / Conditional
|
||
-a ARCH - Mac: disallowed (builds are universal)
|
||
- Windows: x64 | arm64 | win32
|
||
- Linux: x64 (or x86_64) | arm64
|
||
If omitted on Windows/Linux, all standard archs are fetched.
|
||
DONE
|
||
exit 1
|
||
}
|
||
|
||
BUILD_MAC=0
|
||
BUILD_WIN=0
|
||
BUILD_LINUX=0
|
||
arch=""
|
||
while getopts 'p:a:' opt; do
|
||
case $opt in
|
||
p)
|
||
for (( i=0; i<${#OPTARG}; i++ )); do
|
||
case ${OPTARG:i:1} in
|
||
m) BUILD_MAC=1;;
|
||
w) BUILD_WIN=1;;
|
||
l) BUILD_LINUX=1;;
|
||
*) echo "Invalid platform: ${OPTARG:i:1}"; echo; usage;;
|
||
esac
|
||
done;;
|
||
a) arch="$OPTARG";;
|
||
*) usage;;
|
||
esac
|
||
shift $((OPTIND-1)); OPTIND=1
|
||
done
|
||
|
||
# Require at least one platform
|
||
if [[ $BUILD_MAC == 0 ]] && [[ $BUILD_WIN == 0 ]] && [[ $BUILD_LINUX == 0 ]]; then
|
||
usage
|
||
fi
|
||
|
||
# Sanity‑check arch flag vs platform selections
|
||
if [[ $BUILD_MAC == 1 ]]; then
|
||
[[ -n $arch ]] && { echo "-a is not allowed for Mac" >&2; echo; usage; }
|
||
fi
|
||
if [[ $BUILD_WIN == 1 || $BUILD_LINUX == 1 ]]; then
|
||
# arch optional; if provided validate & map aliases now
|
||
if [[ -n $arch ]]; then
|
||
if [[ $BUILD_WIN == 1 && $BUILD_LINUX == 1 ]]; then
|
||
echo "-a cannot be used when building both Windows and Linux simultaneously" >&2; echo; usage
|
||
fi
|
||
if [[ $BUILD_WIN == 1 ]]; then
|
||
case $arch in
|
||
x64) arch="win-x64" ;;
|
||
arm64) arch="win-arm64" ;;
|
||
win32|win-x64|win-arm64) ;;
|
||
*) echo "Invalid Windows arch: $arch" >&2; echo; usage;;
|
||
esac
|
||
fi
|
||
if [[ $BUILD_LINUX == 1 ]]; then
|
||
[[ $arch == x64 ]] && arch="x86_64"
|
||
case $arch in x86_64|arm64) ;; *) echo "Invalid Linux arch: $arch" >&2; echo; usage;; esac
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
function get_utf16_chars {
|
||
str=$(echo -n "$1" | xxd -p | fold -w 2 | sed -r 's/(.+)/\\\\x{\1}\\\\x{00}/')
|
||
# Add NUL padding
|
||
if [ -n "${2:-}" ]; then
|
||
# Multiply characters x 2 for UTF-16
|
||
for i in `seq 1 $(($2 * 2))`; do
|
||
str+=$(echo '\\x{00}')
|
||
done
|
||
fi
|
||
echo $str | xargs | sed 's/ //g'
|
||
}
|
||
|
||
#
|
||
# Make various modifications to the stock Firefox app
|
||
#
|
||
function modify_omni {
|
||
platform=$1
|
||
|
||
mkdir omni
|
||
mv omni.ja omni
|
||
cd omni
|
||
# omni.ja is an "optimized" ZIP file, so use a script from Mozilla to avoid a warning from unzip
|
||
# here and to make it work after rezipping below
|
||
python3 "$APP_ROOT_DIR/scripts/optimizejars.py" --deoptimize ./ ./ ./
|
||
rm -f omni.ja.log
|
||
unzip omni.ja
|
||
rm omni.ja
|
||
|
||
rm -r chrome/pdfjs
|
||
|
||
rm -r modules/narrate
|
||
#rm -r modules/translation
|
||
|
||
rm actors/AboutTranslations{Parent,Child}.sys.mjs
|
||
rm actors/CookieBanner{Parent,Child}.sys.mjs
|
||
rm actors/PictureInPictureChild.sys.mjs
|
||
rm actors/ThumbnailsChild.sys.mjs
|
||
rm actors/Translations{Engine,}{Parent,Child}.sys.mjs
|
||
rm actors/AudioPlayback{Parent,Child}.sys.mjs
|
||
|
||
replace_line 'BROWSER_CHROME_URL:.+' 'BROWSER_CHROME_URL: "chrome:\/\/zotero\/content\/zoteroPane.xhtml",' modules/AppConstants.sys.mjs
|
||
# Used by OSKeyStore as the master-key label, visible in macOS Keychain Access.
|
||
# Verify that OSKeyStore still derives the label from MOZ_APP_BASENAME, so a
|
||
# future Mozilla change to a hardcoded string doesn't silently rebrand the
|
||
# keychain entry back to "Firefox Encrypted Storage".
|
||
replace_line 'MOZ_APP_BASENAME: "Firefox"' 'MOZ_APP_BASENAME: "Zotero"' modules/AppConstants.sys.mjs
|
||
check_line 'STORE_LABEL: AppConstants\.MOZ_APP_BASENAME \+ " Encrypted Storage"' modules/OSKeyStore.sys.mjs
|
||
|
||
# https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/internals/preferences.html
|
||
#
|
||
# It's not clear that most of these do anything anymore when not compiled in, but just in case
|
||
replace_line 'MOZ_REQUIRE_SIGNING:' 'MOZ_REQUIRE_SIGNING: false \&\&' modules/AppConstants.sys.mjs
|
||
replace_line 'MOZ_DATA_REPORTING:' 'MOZ_DATA_REPORTING: false \&\&' modules/AppConstants.sys.mjs
|
||
replace_line 'MOZ_TELEMETRY_REPORTING:' 'MOZ_TELEMETRY_REPORTING: false \&\&' modules/AppConstants.sys.mjs
|
||
replace_line 'MOZ_CRASHREPORTER:' 'MOZ_CRASHREPORTER: false \&\&' modules/AppConstants.sys.mjs
|
||
replace_line 'MOZ_UPDATE_CHANNEL:.+' 'MOZ_UPDATE_CHANNEL: "none",' modules/AppConstants.sys.mjs
|
||
replace_line '"https:\/\/[^\/]+mozilla.com.+"' '""' modules/AppConstants.sys.mjs
|
||
|
||
# Don't use Mozilla Maintenance Service on Windows
|
||
replace_line 'MOZ_MAINTENANCE_SERVICE:' 'MOZ_MAINTENANCE_SERVICE: false \&\&' modules/AppConstants.sys.mjs
|
||
# Continue using app.update.auto in prefs.js on Windows
|
||
replace_line 'PER_INSTALLATION_PREFS_PLATFORMS = \["win"\]' 'PER_INSTALLATION_PREFS_PLATFORMS = []' modules/UpdateUtils.sys.mjs
|
||
|
||
# Prompt if major update is available instead of installing automatically on restart
|
||
replace_line 'if \(!updateAuto\) \{' 'if (update.type == "major") {
|
||
LOG("UpdateService:_selectAndInstallUpdate - prompting because it is a major update");
|
||
AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_SHOWPROMPT_PREF);
|
||
Services.obs.notifyObservers(update, "update-available", "show-prompt");
|
||
return;
|
||
}
|
||
if (!updateAuto) {' modules/UpdateService.sys.mjs
|
||
|
||
# Avoid console warning about resource://gre/modules/FxAccountsCommon.js
|
||
replace_line 'const logins = this._data.logins;' 'const logins = this._data.logins; if (this._data.logins.length != -1) return;' modules/LoginStore.sys.mjs
|
||
|
||
# Prevent error during network requests
|
||
replace_line 'async lazyInit\(\) \{' 'async lazyInit() { if (this.features) return false;' modules/UrlClassifierExceptionListService.sys.mjs
|
||
|
||
# Silence CrashManager "Could not get children of [...]/Crash Reports/events" spam
|
||
replace_line '\/\/ Missing events folders are allowed' '\/\/ Missing events folders are allowed (silence warning)
|
||
if (ex) return entries;' modules/CrashManager.sys.mjs
|
||
|
||
# Several services pull in services-settings (which we strip) and throw
|
||
# at profile-after-change. Remove their #init() methods to prevent errors.
|
||
replace_line 'async #init\(\) \{' 'async #init() {} async _unused_init() {' modules/EssentialDomainsRemoteSettings.sys.mjs
|
||
replace_line 'async #init\(\) \{' 'async #init() {} async _unused_init() {' modules/SimpleURIUnknownSchemesRemoteObserver.sys.mjs
|
||
# RemotePermissionService uses a top-level import, so even loading the
|
||
# module throws
|
||
replace_line 'import \{ RemoteSettings \} from "resource:\/\/services-settings\/remote-settings.sys.mjs";' \
|
||
'const RemoteSettings = () => ({ on() {}, get: async () => [] });' \
|
||
modules/RemotePermissionService.sys.mjs
|
||
|
||
replace_line 'pref\("network.captive-portal-service.enabled".+' 'pref("network.captive-portal-service.enabled", false);' greprefs.js
|
||
replace_line 'pref\("network.connectivity-service.enabled".+' 'pref("network.connectivity-service.enabled", false);' greprefs.js
|
||
replace_line 'pref\("toolkit.telemetry.server".+' 'pref("toolkit.telemetry.server", "");' greprefs.js
|
||
replace_line 'pref\("toolkit.telemetry.unified".+' 'pref("toolkit.telemetry.unified", false);' greprefs.js
|
||
replace_line 'pref\("media.gmp-manager.url".+' 'pref("media.gmp-manager.url", "");' greprefs.js
|
||
|
||
#
|
||
# # Disable transaction timeout
|
||
# perl -pi -e 's/let timeoutPromise/\/*let timeoutPromise/' modules/Sqlite.jsm
|
||
# perl -pi -e 's/return Promise.race\(\[transactionPromise, timeoutPromise\]\);/*\/return transactionPromise;/' modules/Sqlite.jsm
|
||
# rm -f jsloader/resource/gre/modules/Sqlite.jsm
|
||
#
|
||
# Disable unwanted components
|
||
remove_line '(RemoteSettings|services-|telemetry|Telemetry|URLDecorationAnnotationsService)' components/components.manifest
|
||
|
||
file="modules/ActorManagerParent.sys.mjs"
|
||
# Remove deleted actors
|
||
# Entries in the JSWINDOWACTORS/JSPROCESSACTORS literals:
|
||
remove_between '^ AudioPlayback: \{' '^ },' $file
|
||
remove_between '^ CookieBanner: \{' '^ },' $file
|
||
remove_between '^ Thumbnails: \{' '^ },' $file
|
||
remove_between '^ Translations: \{' '^ },' $file
|
||
remove_between '^ TranslationsEngine: \{' '^ },' $file
|
||
# Entries added conditionally after the literals:
|
||
remove_between '^ JSWINDOWACTORS\.AboutTranslations = \{' '^ \};' $file
|
||
remove_between '^ JSWINDOWACTORS\.PictureInPictureLauncher = \{' '^ \};' $file
|
||
remove_between '^ JSWINDOWACTORS\.PictureInPictureToggle = \{' '^ \};' $file
|
||
remove_between '^ JSWINDOWACTORS\.PictureInPicture = \{' '^ \};' $file
|
||
# Do not trigger LoginManager event that logs an error on autocomplete submission
|
||
remove_line 'DOMInputPasswordAdded: \{\},' $file
|
||
|
||
# On Mac/Linux, ignore relative paths in PATH in Subprocess.pathSearch(), used when a bare command is passed to Utilities.Internal.subprocess()
|
||
if [[ $platform != win* ]]; then
|
||
replace_line 'let path = PathUtils.join\(dir, bin\);' 'if (!dir.startsWith("\/")) continue; let path = PathUtils.join(dir, bin);' modules/subprocess/subprocess_unix.sys.mjs
|
||
fi
|
||
|
||
# Remove unwanted files
|
||
pushd modules
|
||
rm Bookmarks*
|
||
rm FxAccounts*
|
||
echo '' > FingerprintingWebCompatService.sys.mjs
|
||
echo '' > PartitioningExceptionListService.sys.mjs
|
||
rm Places*
|
||
echo '' > PlacesExpiration.sys.mjs
|
||
echo '' > PlacesFrecencyRecalculator.sys.mjs
|
||
rm -rf services-settings/*
|
||
touch services-settings/remote-settings.sys.mjs
|
||
# Causes a startup error -- try an empty file or a shim instead?
|
||
#rm Telemetry*
|
||
rm URLDecorationAnnotationsService.sys.mjs
|
||
popd
|
||
pushd chrome/toolkit/content/mozapps/extensions
|
||
rm -rf default-theme
|
||
popd
|
||
|
||
# This file loads remote-settings.sys.mjs, but if it's empty Zotero crashes
|
||
replace_line 'async #init\(\) \{' 'async #init() { if (true) { return; }' modules/URLQueryStrippingListService.sys.mjs
|
||
|
||
# Clear most WebExtension manifest properties
|
||
replace_line 'manifest = normalized.value;' 'manifest = normalized.value;
|
||
if (this.type == "extension") {
|
||
if (!manifest.applications?.zotero?.id) {
|
||
this.manifestError("applications.zotero.id not provided");
|
||
}
|
||
if (!manifest.applications?.zotero?.update_url) {
|
||
this.manifestError("applications.zotero.update_url not provided");
|
||
}
|
||
if (!manifest.applications?.zotero?.strict_max_version) {
|
||
this.manifestError("applications.zotero.strict_max_version not provided");
|
||
}
|
||
manifest.browser_specific_settings = undefined;
|
||
manifest.content_scripts = [];
|
||
manifest.permissions = [];
|
||
manifest.host_permissions = [];
|
||
manifest.web_accessible_resources = undefined;
|
||
manifest.experiment_apis = {};
|
||
}' modules/Extension.sys.mjs
|
||
|
||
# Use applications.zotero instead of applications.gecko
|
||
replace_line 'let bss = manifest.applications\?.gecko' 'let bss = manifest.applications?.zotero' modules/addons/XPIInstall.sys.mjs
|
||
replace_line 'manifest.applications\?.gecko' 'manifest.applications?.zotero' modules/Extension.sys.mjs
|
||
|
||
# When installing addon, use app version instead of toolkit version for targetApplication
|
||
replace_line "id: TOOLKIT_ID," "id: '$APP_ID'," modules/addons/XPIInstall.sys.mjs
|
||
|
||
# Set strictCompatibility to false in beta/dev/source builds to skip strict_max_version check
|
||
replace_line 'addon.strictCompatibility = true;' \
|
||
'let version = Services.appinfo.version;
|
||
addon.strictCompatibility = !version.includes("-beta") && !version.includes("-dev") && !version.includes("SOURCE");' modules/addons/XPIInstall.sys.mjs
|
||
|
||
# In beta/dev/source builds, ignore the persisted strictCompatibility flag for already-installed
|
||
# plugins, so plugins installed on a stable build (where the flag was set to true) aren't marked
|
||
# incompatible after upgrading. The manifest isn't re-parsed on app upgrade, so the flag set at
|
||
# install time sticks around.
|
||
replace_line '!this\.addon\.strictCompatibility' \
|
||
'(!this.addon.strictCompatibility || Services.appinfo.version.includes("-beta") || Services.appinfo.version.includes("-dev") || Services.appinfo.version.includes("SOURCE"))' modules/addons/XPIInstall.sys.mjs
|
||
replace_line '!this\.strictCompatibility &&' \
|
||
'(!this.strictCompatibility || Services.appinfo.version.includes("-beta") || Services.appinfo.version.includes("-dev") || Services.appinfo.version.includes("SOURCE")) &&' modules/addons/XPIDatabase.sys.mjs
|
||
|
||
# Accept zotero@chnm.gmu.edu for target application to allow Zotero 6 plugins to remain
|
||
# installed in Zotero 7
|
||
replace_line "if \(targetApp.id == Services.appinfo.ID\) \{" "if (targetApp.id == 'zotero\@chnm.gmu.edu') targetApp.id = '$APP_ID'; if (targetApp.id == Services.appinfo.ID) {" modules/addons/XPIDatabase.sys.mjs
|
||
|
||
# TEMP: Skip addons without ids until we figure out what's going on with the default theme.
|
||
# This fixes plugin updating and other things.
|
||
replace_line 'return addons;' 'return addons.filter(addon => addon.id);' modules/addons/XPIDatabase.sys.mjs
|
||
|
||
# For updates, look for applications.zotero instead of applications.gecko in manifest.json and
|
||
# use the app id and version for strict_min_version/strict_max_version comparisons
|
||
replace_line 'gecko: \{\},' 'zotero: {},' modules/addons/AddonUpdateChecker.sys.mjs
|
||
replace_line 'if \(!\("gecko" in applications\)\) \{' 'if (!("zotero" in applications)) {' modules/addons/AddonUpdateChecker.sys.mjs
|
||
replace_line '"gecko not in application entry' '"zotero not in application entry' modules/addons/AddonUpdateChecker.sys.mjs
|
||
replace_line 'let app = getProperty\(applications, "gecko", "object"\);' 'let app = getProperty(applications, "zotero", "object");' modules/addons/AddonUpdateChecker.sys.mjs
|
||
replace_line "id: TOOLKIT_ID," "id: '$APP_ID'," modules/addons/AddonUpdateChecker.sys.mjs
|
||
replace_line 'lazy.AddonManagerPrivate.webExtensionsMinPlatformVersion' '"7.0"' modules/addons/AddonUpdateChecker.sys.mjs
|
||
replace_line 'result.targetApplications.push' 'false && result.targetApplications.push' modules/addons/AddonUpdateChecker.sys.mjs
|
||
# In beta/dev/source builds, don't set strictCompatibility on parsed update entries so that
|
||
# AddonUpdateChecker doesn't reject an available update whose maxVersion is lower than the
|
||
# current (non-stable) app version.
|
||
replace_line 'result\.strictCompatibility = appEntry\.maxVersion != "\*";' \
|
||
'let appVer = Services.appinfo.version; result.strictCompatibility = appEntry.maxVersion != "*" && !appVer.includes("-beta") && !appVer.includes("-dev") && !appVer.includes("SOURCE");' modules/addons/AddonUpdateChecker.sys.mjs
|
||
# Set uninstall flag to true if the update config has it set
|
||
replace_line 'targetApplications: \[appEntry\],' \
|
||
'targetApplications: \[appEntry\],
|
||
uninstall: getProperty(update, "uninstall", "boolean"),' modules/addons/AddonUpdateChecker.sys.mjs
|
||
|
||
# Prevent automatic installation of default theme
|
||
# (chrome/toolkit/content/mozapps/extensions/default-theme, removed above)
|
||
replace_line 'this.maybeInstallBuiltinAddon\(' 'if (false) this.maybeInstallBuiltinAddon(' modules/addons/XPIProvider.sys.mjs
|
||
|
||
# Don't log a warning when checking 'distribution/extensions' for addons
|
||
replace_line 'logger.warn\(`Checking' 'logger.debug(`Checking' modules/addons/XPIProvider.sys.mjs
|
||
|
||
# Allow addon installation by bypassing confirmation dialogs. If we want a confirmation dialog,
|
||
# we need to either add gXPInstallObserver from browser-addons.js [1][2] or provide our own with
|
||
# Ci.amIWebInstallPrompt [3].
|
||
#
|
||
# [1] https://searchfox.org/mozilla-esr102/rev/5a6d529652045050c5cdedc0558238949b113741/browser/base/content/browser.js#1902-1923
|
||
# [2] https://searchfox.org/mozilla-esr102/rev/5a6d529652045050c5cdedc0558238949b113741/browser/base/content/browser-addons.js#201
|
||
# [3] https://searchfox.org/mozilla-esr102/rev/5a6d529652045050c5cdedc0558238949b113741/toolkit/mozapps/extensions/AddonManager.sys.mjs#3114-3124
|
||
replace_line 'if \(info.addon.installPermissions\) \{' 'if (false) {' modules/AddonManager.sys.mjs
|
||
replace_line '\} else if \(info.addon.sitePermissions\) \{' '} else if (false) {' modules/AddonManager.sys.mjs
|
||
replace_line '\} else if \(requireConfirm\) \{' '} else if (false) {' modules/AddonManager.sys.mjs
|
||
|
||
# Make addon listener methods wait for promises, to allow calling asynchronous plugin `shutdown`
|
||
# and `uninstall` methods in our `onInstalling` handler
|
||
replace_line 'callAddonListeners\(aMethod' 'async callAddonListeners(aMethod' modules/AddonManager.sys.mjs
|
||
# Don't need this one to be async, but we can't easily avoid modifying its `listener[aMethod].apply()` call
|
||
replace_line 'callManagerListeners\(aMethod' 'async callManagerListeners(aMethod' modules/AddonManager.sys.mjs
|
||
replace_line 'AddonManagerInternal.callAddonListeners.apply\(AddonManagerInternal, aArgs\);' \
|
||
'return AddonManagerInternal.callAddonListeners.apply(AddonManagerInternal, aArgs);' modules/AddonManager.sys.mjs
|
||
replace_line 'listener\[aMethod\].apply\(listener, aArgs\);' \
|
||
'let maybePromise = listener[aMethod].apply(listener, aArgs);
|
||
if (maybePromise && maybePromise.then) await maybePromise;' modules/AddonManager.sys.mjs
|
||
replace_line 'AddonManagerPrivate.callAddonListeners' 'await AddonManagerPrivate.callAddonListeners' modules/addons/XPIInstall.sys.mjs
|
||
replace_line 'let uninstall = \(\) => \{' 'let uninstall = async () => {' modules/addons/XPIInstall.sys.mjs
|
||
replace_line 'cancelUninstallAddon\(aAddon\)' 'async cancelUninstallAddon(aAddon)' modules/addons/XPIInstall.sys.mjs
|
||
# Check for `uninstall` flag in update config and uninstall the addon if set
|
||
replace_line 'if \(update && !this.addon.location.locked\) \{' \
|
||
'if (update && !this.addon.location.locked) {
|
||
if (update.uninstall) {
|
||
let aId = this.addon.id;
|
||
logger.debug(`AddonUpdateChecker: uninstall addon \${aId} with uninstall flag`);
|
||
let addon = await AddonManager.getAddonByID(aId);
|
||
if (addon && (addon.permissions & AddonManager.PERM_CAN_UNINSTALL)) {
|
||
try {
|
||
addon.uninstall();
|
||
} catch (err) {
|
||
logger.error(`AddonUpdateChecker: error uninstalling addon \${aId} with uninstall flag`, err);
|
||
}
|
||
sendUpdateAvailableMessages(this, null);
|
||
return;
|
||
}
|
||
else {
|
||
logger.error(`AddonUpdateChecker: addon \${aId} with uninstall flag not found or cannot be uninstalled`);
|
||
sendUpdateAvailableMessages(this, null);
|
||
return;
|
||
}
|
||
}
|
||
' modules/addons/XPIInstall.sys.mjs
|
||
|
||
# Prevent login manager from trying to load FxAccountsCommon.sys.mjs
|
||
replace_line 'return login.hostname == lazy.FXA_PWDMGR_HOST;' 'return false;' modules/storage-json.sys.mjs
|
||
|
||
# No idea why this is necessary, but without it initialization fails with "TypeError: "constructor" is read-only"
|
||
replace_line 'LoginStore.prototype.constructor = LoginStore;' '\/\/LoginStore.prototype.constructor = LoginStore;' modules/LoginStore.sys.mjs
|
||
#
|
||
# # Allow proxy password saving
|
||
# perl -pi -e 's/get _inPrivateBrowsing\(\) \{/get _inPrivateBrowsing() {if (true) { return false; }/' components/nsLoginManagerPrompter.js
|
||
#
|
||
# # Change text in update dialog
|
||
# perl -pi -e 's/A security and stability update for/A new version of/' chrome/en-US/locale/en-US/mozapps/update/updates.properties
|
||
# perl -pi -e 's/updateType_major=New Version/updateType_major=New Major Version/' chrome/en-US/locale/en-US/mozapps/update/updates.properties
|
||
# perl -pi -e 's/updateType_minor=Security Update/updateType_minor=New Version/' chrome/en-US/locale/en-US/mozapps/update/updates.properties
|
||
# perl -pi -e 's/update for &brandShortName; as soon as possible/update as soon as possible/' chrome/en-US/locale/en-US/mozapps/update/updates.dtd
|
||
#
|
||
# Set available locales
|
||
cp "$APP_ROOT_DIR/assets/multilocale.txt" res/multilocale.txt
|
||
|
||
# Use Zotero URL opening in Mozilla dialogs (e.g., app update dialog)
|
||
replace_line 'function openURL\(aURL\) \{' 'function openURL(aURL) {let {Zotero} = ChromeUtils.importESModule("chrome:\/\/zotero\/content\/zotero.mjs"); Zotero.launchURL(aURL); if (true) { return; }' chrome/toolkit/content/global/contentAreaUtils.js
|
||
|
||
#
|
||
# Modify Add-ons window
|
||
#
|
||
|
||
# Prevent display: block from overriding display: none on <hr>s
|
||
replace_line 'display: block !important;' 'display: block;' chrome/toolkit/content/global/elements/panel-list.css
|
||
|
||
file="chrome/toolkit/content/mozapps/extensions/aboutaddons.css"
|
||
echo >> $file
|
||
# Hide the search bar and the whole sidebar, since we only ever show plugins and the main pane
|
||
# is already headed "Manage Your Plugins"
|
||
echo '.main-search, #sidebar { display: none; }' >> $file
|
||
# Center the content in the window now that it isn't offset by the sidebar
|
||
echo '#full { grid-template-columns: 1fr; }' >> $file
|
||
echo '#content { max-width: calc(var(--page-main-content-width) + var(--main-margin-start)); margin-inline: auto; }' >> $file
|
||
echo '.main-heading { margin-top: 2em; }' >> $file
|
||
# Hide Details/Permissions tabs in addon details so we only show details
|
||
echo 'addon-details > button-group { display: none !important; }' >> $file
|
||
# Hide "Run on sites with restrictions" row and helper message
|
||
echo '.addon-detail-row-quarantined-domains { display: none; }' >> $file
|
||
echo '.addon-detail-help-row:has([data-l10n-id="addon-detail-quarantined-domains-help"]) { display: none; }' >> $file
|
||
# Hide "Report" button from plugin menu
|
||
echo 'addon-card addon-options hr:first-of-type { display: none }' >> $file
|
||
echo '[data-l10n-id="report-addon-button"] { display: none }' >> $file
|
||
# Hide "Debug Addons" and "Manage Extension Shortcuts"
|
||
echo 'panel-item[action="debug-addons"], panel-item[action="reset-update-states"] + hr, panel-item[action="manage-shortcuts"] { display: none }' >> $file
|
||
# Show cursor feedback on plugin homepage links
|
||
echo '.addon-detail-row-homepage .text-link { cursor: pointer; color: LinkText; }' >> $file
|
||
echo '.addon-detail-row-homepage .text-link:hover { text-decoration: underline; }' >> $file
|
||
|
||
file="chrome/toolkit/content/mozapps/extensions/aboutaddons-utils.mjs"
|
||
# Hide unsigned-addon warning
|
||
replace_line 'export function isUnsignedWarningMessageDisabled\(\) \{' \
|
||
'export function isUnsignedWarningMessageDisabled() {if (true) return true;' $file
|
||
# Use our own localized string for blocked plugin notification
|
||
replace_line 'details-notification-hard-blocked-\$\{typeSuffix\}' 'plugins-blocked-plugin' $file
|
||
# Hide Recommendations tab in sidebar and recommendations in main pane
|
||
replace_line 'function isDiscoverEnabled\(\) \{' 'function isDiscoverEnabled() {return false;' $file
|
||
|
||
file="chrome/toolkit/content/mozapps/extensions/components/addon-details.mjs"
|
||
# Hide Private Browsing setting in addon details
|
||
replace_line 'pbRow\.' '\/\/pbRow.' $file
|
||
replace_line 'let isAllowed = await isAllowedInPrivateBrowsing' '\/\/let isAllowed = await isAllowedInPrivateBrowsing' $file
|
||
# Open plugin links in external browser
|
||
replace_line 'let homepageURL = homepageRow.querySelector\(\"a\"\);' 'let homepageURL = homepageRow.querySelector(\"\.text-link\");' $file
|
||
replace_line 'homepageURL.href = addon.homepageURL;' 'homepageURL.setAttribute("href", addon.homepageURL);' $file
|
||
replace_line '<a target="_blank" dir="ltr"><\/a>' \
|
||
'<label target="_blank" class="text-link" dir="ltr"><\/label>' $file
|
||
|
||
file="chrome/toolkit/content/mozapps/extensions/components/addon-card.mjs"
|
||
# Use our own strings for the removal prompt
|
||
replace_line 'let \{ BrowserAddonUI \} = windowRoot.window;' '' $file
|
||
replace_line 'await BrowserAddonUI.promptRemoveExtension' 'promptRemoveExtension' $file
|
||
|
||
# Customize empty-list message
|
||
replace_line 'createEmptyListMessage\(\) {' 'createEmptyListMessage() {
|
||
var p = document.createElement("p");
|
||
p.id = "empty-list-message";
|
||
return p;' chrome/toolkit/content/mozapps/extensions/components/addon-list.mjs
|
||
|
||
# Add zotero.ftl to the addons page for our own localized strings
|
||
replace_line 'href="toolkit\/about\/aboutAddons.ftl"' 'href="toolkit\/about\/aboutAddons.ftl" \/>\n <link rel="localization" href="zotero.ftl"' \
|
||
chrome/toolkit/content/mozapps/extensions/aboutaddons.html
|
||
|
||
# TODO: Use our own strings, but for now fix the bundled English ones
|
||
replace_line 'Manage Your Extensions' 'Manage Your Plugins' localization/en-US/toolkit/about/aboutAddons.ftl
|
||
replace_line 'Add-on' 'Plugin' localization/en-US/toolkit/about/aboutAddons.ftl
|
||
replace_line 'add-ons' 'plugins' localization/en-US/toolkit/about/aboutAddons.ftl
|
||
replace_line 'Select add-on to install' 'Select plugin to install' localization/en-US/toolkit/about/aboutAddons.ftl
|
||
|
||
replace_line 'pref\("extensions.htmlaboutaddons.recommendations.enabled".+' 'pref("extensions.htmlaboutaddons.recommendations.enabled", false);' greprefs.js
|
||
|
||
# Hide Report option
|
||
replace_line 'pref\("extensions.abuseReport.enabled".+' 'pref("extensions.abuseReport.enabled", false);' greprefs.js
|
||
|
||
# The first displayed Services.prompt dialog's size jumps around because sizeToContent() is called twice
|
||
# Fix by preventing the first sizeToContent() call if the icon hasn't been loaded yet
|
||
replace_line 'window.sizeToContent\(\);' 'if (ui.infoIcon.complete) window.sizeToContent();' chrome/toolkit/content/global/commonDialog.js
|
||
replace_line 'ui.infoIcon.addEventListener' 'if (!ui.infoIcon.complete) ui.infoIcon.addEventListener' chrome/toolkit/content/global/commonDialog.js
|
||
|
||
# Import style into built-in dialogs
|
||
replace_line 'id=\"commonDialogWindow\"' \
|
||
'id=\"commonDialogWindow\" class=\"zotero-dialog\" drawintitlebar-platforms=\"mac\"' \
|
||
chrome/toolkit/content/global/commonDialog.xhtml
|
||
# commonDialog.css link is split across multiple lines, so we have to do a weird substitution,
|
||
# so check the one-line global.css to make sure the format hasn't changed
|
||
check_line '<html:link rel="stylesheet" href="chrome:\/\/global\/skin\/global.css" \/>' chrome/toolkit/content/global/commonDialog.xhtml
|
||
replace_line 'chrome:\/\/global\/skin\/commonDialog.css"' \
|
||
'chrome:\/\/global\/skin\/commonDialog.css"\/>
|
||
<html:link rel="stylesheet" href="chrome:\/\/zotero-platform\/content\/zotero.css"' \
|
||
chrome/toolkit/content/global/commonDialog.xhtml
|
||
# commonDialog.xhtml can be opened via Services.prompt in the Profile Manager, so check for a profile first
|
||
replace_line 'function commonDialogOnLoad\(\) \{' \
|
||
'function commonDialogOnLoad() {
|
||
try {
|
||
Services.dirsvc.get(\"ProfD\", Ci.nsIFile);
|
||
Services.scriptloader.loadSubScript(\"chrome:\/\/zotero\/content\/include.js\", this);
|
||
Services.scriptloader.loadSubScript(\"chrome:\/\/zotero\/content\/titlebar.js\", this);
|
||
Services.scriptloader.loadSubScript(\"chrome:\/\/zotero\/content\/customElements.js\", this);
|
||
} catch (e) {}' \
|
||
chrome/toolkit/content/global/commonDialog.js
|
||
|
||
# Use native checkbox instead of Firefox-themed version in prompt dialogs
|
||
replace_line '<xul:checkbox' '<xul:checkbox native=\"true\"' chrome/toolkit/content/global/commonDialog.xhtml
|
||
|
||
# The <browser> CE appends its autoscroll <popup> to document.documentElement, which doesn't work in zoteroPane.xhtml
|
||
# (in Firefox browser.xhtml, document.documentElement is <html>, which can contain <popup>s; in zoteroPane.xhtml, it's
|
||
# <window>, which can't)
|
||
# Fix by appending it to a <popupset> instead
|
||
replace_line 'document.documentElement.appendChild\(this._autoScrollPopup\);' 'let popupset = document.querySelector("popupset");
|
||
if (!popupset) {
|
||
popupset = document.createXULElement("popupset");
|
||
document.documentElement.appendChild(popupset);
|
||
}
|
||
popupset.appendChild(this._autoScrollPopup);' chrome/toolkit/content/global/elements/browser-custom-element.mjs
|
||
|
||
# Add the dropmarker for toolbarbuttons with wantdropmarker, which Firefox no longer creates
|
||
replace_line 'this.appendChild\(this.constructor.fragment.cloneNode\(true\)\);' \
|
||
'this.appendChild(this.constructor.fragment.cloneNode(true));
|
||
|
||
if (this.hasAttribute("wantdropmarker")) {
|
||
let dropmarker = document.createXULElement("dropmarker");
|
||
dropmarker.setAttribute("type", "menu");
|
||
dropmarker.className = "toolbarbutton-menu-dropmarker";
|
||
this.appendChild(dropmarker);
|
||
}' chrome/toolkit/content/global/elements/toolbarbutton.js
|
||
# Let clicks on the dropmarker pass through to the toolbarbutton, which only opens its menu
|
||
# when it's the original event target, as xul.css did when Firefox created the dropmarker
|
||
echo '.toolbarbutton-menu-dropmarker { pointer-events: none; }' >> chrome/toolkit/content/global/xul.css
|
||
|
||
# Remove non-native text input styles
|
||
remove_between 'html\|input\:where\(' '^}' chrome/toolkit/skin/classic/global/global-shared.css
|
||
|
||
# Prevent window dragging on scrollbars
|
||
echo 'scrollbar { -moz-window-dragging: no-drag; }' >> chrome/toolkit/res/scrollbars.css
|
||
|
||
# Provide a mechanism for non-UA stylesheets to override the overflow property
|
||
# of a text control's anonymous text node child
|
||
echo '::placeholder, ::-moz-text-control-editing-root, ::-moz-text-control-preview {
|
||
overflow: var(--moz-text-control-overflow);
|
||
}' >> chrome/toolkit/res/forms.css
|
||
|
||
# Size an autocomplete popup to the input that opened it, or to an ancestor that designates
|
||
# itself as the width container. Firefox sizes the popup to its content. (For creator inputs.)
|
||
replace_line '\/\/ invalidate\(\) depends on the width attribute' \
|
||
'let widthElement = aElement.closest(".autocomplete-popup-width-container") || aElement;
|
||
this.style.setProperty("--panel-width", Math.max(widthElement.getBoundingClientRect().width, 100) + "px");
|
||
\/\/ invalidate() depends on the width attribute' \
|
||
chrome/toolkit/content/global/elements/autocomplete-popup.js
|
||
|
||
zip -qr9XD omni.ja *
|
||
mv omni.ja ..
|
||
cd ..
|
||
python3 "$APP_ROOT_DIR/scripts/optimizejars.py" --optimize ./ ./ ./
|
||
rm -rf omni
|
||
|
||
# Unzip browser/omni.ja and leave unzipped
|
||
cd browser
|
||
mkdir omni
|
||
mv omni.ja omni
|
||
cd omni
|
||
ls -la
|
||
set +e
|
||
unzip omni.ja
|
||
set -e
|
||
rm omni.ja
|
||
|
||
# Remove Firefox update URLs
|
||
remove_line 'pref\("app.update.url.(manual|details)' defaults/preferences/firefox-branding.js
|
||
|
||
# Remove Firefox overrides (e.g., to use Firefox-specific strings for connection errors)
|
||
remove_line '(override)' chrome/chrome.manifest
|
||
|
||
# Remove WebExtension APIs
|
||
remove_line ext-browser.json components/components.manifest
|
||
|
||
# Don't open a second window if app is already open when launching .exe (Windows) or running via
|
||
# command line (macOS)
|
||
replace_line 'function dch_handle\(cmdLine\) \{' 'function dch_handle(cmdLine) {
|
||
if (cmdLine.state == Ci.nsICommandLine.STATE_REMOTE_AUTO) { return; }
|
||
' modules/BrowserContentHandler.sys.mjs
|
||
}
|
||
|
||
mkdir -p xulrunner
|
||
cd xulrunner
|
||
|
||
if [ $BUILD_MAC == 1 ]; then
|
||
GECKO_VERSION="$GECKO_VERSION_MAC"
|
||
DOWNLOAD_URL="https://ftp.mozilla.org/pub/firefox/releases/$GECKO_VERSION"
|
||
rm -rf Firefox.app
|
||
|
||
if [ -e "Firefox $GECKO_VERSION.app.zip" ]; then
|
||
echo "Using Firefox $GECKO_VERSION.app.zip"
|
||
unzip "Firefox $GECKO_VERSION.app.zip"
|
||
else
|
||
curl -fo Firefox.dmg "$DOWNLOAD_URL/mac/en-US/Firefox%20$GECKO_VERSION.dmg"
|
||
set +e
|
||
hdiutil detach -quiet /Volumes/Firefox 2>/dev/null
|
||
set -e
|
||
hdiutil attach -quiet Firefox.dmg
|
||
cp -a /Volumes/Firefox/Firefox.app .
|
||
# Store local copy of unmodified app
|
||
zip -r "Firefox $GECKO_VERSION.app.zip" Firefox.app
|
||
hdiutil detach -quiet /Volumes/Firefox
|
||
fi
|
||
|
||
# Download custom components (e.g., XUL), as an xz-compressed tarball of the MacOS folder with
|
||
# custom files in it
|
||
echo
|
||
rm -rf MacOS
|
||
if [ -n "$custom_components_hash_mac" ]; then
|
||
if [ -e "Firefox $GECKO_VERSION MacOS.zip" ]; then
|
||
echo "Using Firefox $GECKO_VERSION MacOS.zip"
|
||
unzip "Firefox $GECKO_VERSION MacOS.zip"
|
||
else
|
||
echo "Downloading custom Firefox components"
|
||
echo
|
||
curl -o MacOS.tar.xz "${custom_components_url}mac/$custom_components_hash_mac.tar.xz"
|
||
|
||
# Verify hash
|
||
if [[ "`uname`" = "Darwin" ]]; then
|
||
shasum="shasum -a 256"
|
||
else
|
||
shasum=sha256sum
|
||
fi
|
||
echo
|
||
echo "$custom_components_hash_mac MacOS.tar.xz" | $shasum -c -
|
||
echo
|
||
|
||
tar xvf MacOS.tar.xz
|
||
fi
|
||
echo
|
||
fi
|
||
|
||
pushd Firefox.app/Contents/Resources
|
||
modify_omni mac
|
||
popd
|
||
|
||
# Replace "FirefoxCP" with "ZoteroCP" for subprocesses ("Isolated Web Content", "Socket Process", "Web Content", etc.)
|
||
info_plist=Firefox.app/Contents/MacOS/plugin-container.app/Contents/Resources/English.lproj/InfoPlist.strings
|
||
from=$(get_utf16_chars "FirefoxCP")
|
||
to=$(get_utf16_chars "ZoteroCP")
|
||
perl -pi -e "s/$from/$to/" $info_plist
|
||
# Check for UTF-16 "ZoteroCP"
|
||
if ! grep -a -q "Z.o.t.e.r.o.C.P." $info_plist; then
|
||
echo '"ZoteroCP" not found in InfoPlist.strings after replacement'
|
||
exit 1
|
||
fi
|
||
|
||
rm -f Firefox.dmg
|
||
|
||
echo $("$SCRIPT_DIR/xulrunner_hash" -p m) > hash-mac
|
||
fi
|
||
|
||
if [ $BUILD_WIN == 1 ]; then
|
||
GECKO_VERSION="$GECKO_VERSION_WIN"
|
||
DOWNLOAD_URL="https://ftp.mozilla.org/pub/firefox/releases/$GECKO_VERSION"
|
||
|
||
if [[ -n $arch ]]; then
|
||
arch_list=("$(get_canonical_arch w $arch)")
|
||
else
|
||
arch_list=(win-x64 win-arm64 win32)
|
||
fi
|
||
for arch in "${arch_list[@]}"; do
|
||
xdir=firefox-$arch
|
||
|
||
rm -rf $xdir
|
||
mkdir $xdir
|
||
|
||
archived_file="Firefox Setup $GECKO_VERSION-$arch.exe"
|
||
if [ -e "$archived_file" ]; then
|
||
echo "Using $archived_file"
|
||
cp "$archived_file" "Firefox%20Setup%20$GECKO_VERSION.exe"
|
||
else
|
||
if [ $arch = "win-x64" ]; then
|
||
moz_arch=win64
|
||
elif [ $arch = "win-arm64" ]; then
|
||
moz_arch=win64-aarch64
|
||
else
|
||
moz_arch=$arch
|
||
fi
|
||
curl -fO "$DOWNLOAD_URL/$moz_arch/en-US/Firefox%20Setup%20$GECKO_VERSION.exe"
|
||
# Store local copy of unmodified app
|
||
cp "Firefox%20Setup%20$GECKO_VERSION.exe" "$archived_file"
|
||
fi
|
||
|
||
7z x Firefox%20Setup%20$GECKO_VERSION.exe -o$xdir 'core/*'
|
||
mv $xdir/core $xdir-core
|
||
rm -rf $xdir
|
||
mv $xdir-core $xdir
|
||
|
||
# Download custom components, as an architecture-specific ZIP containing xul.dll, etc.
|
||
echo
|
||
hash_arch_name="${arch/-/_}"
|
||
arch_var_name="custom_components_hash_${hash_arch_name}"
|
||
hash=${!arch_var_name:-}
|
||
if [ -n "$hash" ]; then
|
||
zipfile="Firefox $GECKO_VERSION-$arch Components.zip"
|
||
# ZIP filename doesn't include "esr" or "win-"
|
||
url="${custom_components_url}win/${GECKO_VERSION//esr}-${arch#win-}-$hash.zip"
|
||
|
||
if [[ "$(uname)" = "Darwin" ]]; then
|
||
shasum="shasum -a 256"
|
||
else
|
||
shasum=sha256sum
|
||
fi
|
||
|
||
download_zip() {
|
||
echo "Downloading custom Firefox components"
|
||
echo
|
||
echo $url
|
||
curl -fo "$zipfile" "$url"
|
||
}
|
||
|
||
verify_hash() {
|
||
echo "$hash $zipfile" | $shasum -c -
|
||
}
|
||
|
||
# Download if file doesn't exist
|
||
if [ ! -e "$zipfile" ]; then
|
||
download_zip
|
||
fi
|
||
|
||
echo
|
||
if ! verify_hash; then
|
||
echo "SHA hash mismatch. Redownloading ZIP…"
|
||
rm -f "$zipfile"
|
||
download_zip
|
||
echo
|
||
if ! verify_hash; then
|
||
echo "Hash still doesn't match. Aborting."
|
||
exit 1
|
||
fi
|
||
fi
|
||
echo
|
||
|
||
unzip -o "$zipfile" -d "$xdir"
|
||
echo
|
||
fi
|
||
|
||
pushd $xdir
|
||
|
||
#
|
||
# NOTE: Below is disabled, since the full UTF-16 string no longer appears directly in the DLL
|
||
# -- it's now truncated after "e594e8d1" for x64/win32 and doesn't appear at all for ARM64
|
||
#
|
||
|
||
# Replace "Mozilla-1de4eec8-1241-4177-a864-e594e8d1fb38" with "Zotero" for C:\ProgramData directory
|
||
#
|
||
# Mozilla uses a UUID in the path because they previously used just "Mozilla" and needed to
|
||
# recreate the folder with correct permissions for security reasons, but we never had a folder in
|
||
# ProgramData, so we can just create it as "Zotero". Instead of using a custom xul.dll, just
|
||
# replace the hard-coded string with "Zotero" and add a bunch of NULs.
|
||
#
|
||
#from=$(get_utf16_chars "Mozilla-1de4eec8-1241-4177-a864-e594e8d1fb38")
|
||
#to=$(get_utf16_chars "Zotero" 38)
|
||
#perl -pe "s/$from/$to/" < xul.dll > xul.dll.new
|
||
#mv xul.dll.new xul.dll
|
||
|
||
# Check for UTF-16 "Zotero" in DLL
|
||
#
|
||
# (The macOS strings command doesn't have an encoding option, so skip on macOS. You need to
|
||
# build on Windows to make an installer, so a Windows build from macOS likely isn't being
|
||
# deployed.)
|
||
#
|
||
#if [[ "`uname`" != "Darwin" ]] && [[ -z "$(strings -e l xul.dll | grep -m 1 Zotero)" ]]; then
|
||
# echo '"Zotero" not found in xul.dll after replacement'
|
||
# exit 1
|
||
#fi
|
||
|
||
# We re-sign DLL in build.sh, but presumably this file, which is for the Widevine CDM,
|
||
# isn't vaid anymore
|
||
rm xul.dll.sig
|
||
|
||
modify_omni $arch
|
||
# Disable skeleton UI window
|
||
# https://forums.zotero.org/discussion/comment/437636/#Comment_437636
|
||
replace_line 'pref\("browser\.startup\.preXulSkeletonUI", true\);' 'pref("browser.startup.preXulSkeletonUI", false);' defaults/preferences/firefox.js
|
||
popd
|
||
|
||
# Uncomment to create local copies for reuse
|
||
#cp "Firefox%20Setup%20$GECKO_VERSION.exe" "Firefox Setup $GECKO_VERSION-$arch.exe"
|
||
rm "Firefox%20Setup%20$GECKO_VERSION.exe"
|
||
echo
|
||
echo
|
||
|
||
echo "$( "$SCRIPT_DIR/xulrunner_hash" -p w -a "$arch" )" > "hash-$arch"
|
||
done
|
||
fi
|
||
|
||
if [ $BUILD_LINUX == 1 ]; then
|
||
GECKO_VERSION="$GECKO_VERSION_LINUX"
|
||
DOWNLOAD_URL="https://ftp.mozilla.org/pub/firefox/releases/$GECKO_VERSION"
|
||
|
||
if [[ -n $arch ]]; then
|
||
arch_list=("$arch")
|
||
else
|
||
arch_list=(x86_64 arm64)
|
||
fi
|
||
for arch in "${arch_list[@]}"; do
|
||
xdir="firefox-linux-$arch"
|
||
rm -rf $xdir
|
||
|
||
archived_file="firefox-$GECKO_VERSION-$arch.tar.xz"
|
||
if [ -e "$archived_file" ]; then
|
||
echo "Using $archived_file"
|
||
cp "$archived_file" "firefox-$GECKO_VERSION.tar.xz"
|
||
else
|
||
if [ $arch = "arm64" ]; then
|
||
moz_arch=aarch64
|
||
else
|
||
moz_arch=$arch
|
||
fi
|
||
curl -fO "$DOWNLOAD_URL/linux-$moz_arch/en-US/firefox-$GECKO_VERSION.tar.xz"
|
||
# Store local copy of unmodified app
|
||
cp "firefox-$GECKO_VERSION.tar.xz" "$archived_file"
|
||
fi
|
||
|
||
tar xvf firefox-$GECKO_VERSION.tar.xz
|
||
mv firefox $xdir
|
||
|
||
pushd $xdir
|
||
modify_omni $arch
|
||
popd
|
||
|
||
rm "firefox-$GECKO_VERSION.tar.xz"
|
||
|
||
echo "$( $SCRIPT_DIR/xulrunner_hash -p l -a "$arch" )" > "hash-linux-${arch}"
|
||
done
|
||
fi
|
||
|
||
echo Done
|