#!/bin/bash # # Fennec build scripts # Copyright (C) 2020-2024 Matías Zúñiga, Andrew Nayenko, Tavi # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # set -e if [ -z "$1" ] || [ -z "$2" ]; then echo "Usage: $0 versionName versionCode" >&1 exit 1 fi # shellcheck source=paths.sh source "$(dirname "$0")/paths.sh" function localize_maven { # Replace custom Maven repositories with mavenLocal() find ./* -name '*.gradle' -type f -print0 | xargs -0 \ sed -n -i \ -e '/maven {/{:loop;N;/}$/!b loop;/plugins.gradle.org/!s/maven .*/mavenLocal()/};p' # Make gradlew scripts call our Gradle wrapper find ./* -name gradlew -type f | while read -r gradlew; do echo -e '#!/bin/sh\ngradle "$@"' > "$gradlew" chmod 755 "$gradlew" done } function apply_patch { echo "Apply $1" patch -p1 --no-backup-if-mismatch --quiet < "$1" } # Set up Rust rustup default 1.93.0 # # Fenix # pushd "$fenix" # Set up the app ID, version name and version code sed -i \ -e 's|org\.mozilla\.firefox|lol.smesh.felice|' \ -e "s/Config.releaseVersionName(project)/'$1'/" \ -e "s/Config.generateFennecVersionCode(abi)/$2/" \ app/build.gradle sed -i \ -e '/android:targetPackage/s/org\.mozilla\.firefox/lol.smesh.felice/' \ app/src/release/res/xml/shortcuts.xml # Disable crash reporting sed -i -e '/CRASH_REPORTING/s/true/false/' app/build.gradle # Disable MetricController sed -i -e '/TELEMETRY/s/true/false/' app/build.gradle # Let it be Felice sed -i -e 's/Firefox Daylight/Felice/; s/Firefox/Felice/g' \ app/src/*/res/values*/*strings.xml # Fenix uses reflection to create a instance of profile based on the text of # the label, see # app/src/main/java/org/mozilla/fenix/perf/ProfilerStartDialogFragment.kt#185 sed -i \ -e 's/ProfilerSettings.Firefox/ProfilerSettings.Felice/' \ app/src/main/java/org/mozilla/fenix/perf/ProfilerStartDialogFragment.kt sed -i \ -e '/Firefox(.*, .*)/s/Firefox/Felice/' \ -e 's/firefox_threads/felice_threads/' \ -e 's/firefox_features/felice_features/' \ app/src/main/java/org/mozilla/fenix/perf/ProfilerUtils.kt # Replace proprietary artwork sed -i -e 's|@drawable/animated_splash_screen<|@drawable/splash_screen<|' \ app/src/main/res/values-v*/styles.xml find "$patches/fenix-overlay" -type f | while read -r src; do dst=app/src/release/${src#"$patches/fenix-overlay/"} mkdir -p "$(dirname "$dst")" cp "$src" "$dst" done # Drop the Fennec fox vector; the release overlay provides Felice webps at every density rm -f app/src/main/res/drawable/ic_firefox.xml # Route completed .xpi downloads into AddonManager instead of the download-complete snackbar sed -i \ -e '/^import org\.mozilla\.fenix\.components\.AppStore$/a\ import org.mozilla.fenix.ext.components' \ -e '/\/\/ If the download is just paused/i\ if (downloadJobStatus == Status.COMPLETED \&\&\ (downloadState.contentType == "application\/x-xpinstall" ||\ downloadState.fileName?.endsWith(".xpi") == true)) {\ val safeContext = context ?: return\ val fileUri = "file:\/\/" + downloadState.filePath\ safeContext.components.addonManager.installAddon(\ fileUri,\ mozilla.components.concept.engine.webextension.InstallationMethod.FROM_FILE,\ onSuccess = { },\ onError = { _ -> },\ )\ return\ }\ ' app/src/main/java/org/mozilla/fenix/browser/DownloadUtils.kt # Register as handler for .xpi extension files sed -i '//i\ \ \ \ \ \ \ \ <\/intent-filter>\ \ \ \ \ \ \ \ \ <\/intent-filter>\ \ \ \ \ \ \ \ \ \ <\/intent-filter>\ ' app/src/main/AndroidManifest.xml # There are a lot of "No cast needed" warnings in the generated code sed -i -e '/compilerOptions.allWarningsAsErrors/s/true/false/' build.gradle # Enable about:config sed -i \ -e 's/aboutConfigEnabled(.*)/aboutConfigEnabled(true)/' \ app/src/*/java/org/mozilla/fenix/*/GeckoProvider.kt # Disable remote improvements by default sed -i \ -e '/android:defaultValue=/s/"true"/"false"/' \ app/src/main/res/xml/remote_improvements_preferences.xml # Add wallpaper URL echo 'https://gitlab.com/relan/fennecmedia/-/raw/master/wallpapers/android' > .wallpaper_url # Set up target parameters case $(echo "$2" | cut -c 6) in 0) abi=armeabi-v7a target=arm-linux-androideabi echo "ARM" > "$llvm/targets_to_build" rusttarget=arm rustup target add thumbv7neon-linux-androideabi rustup target add armv7-linux-androideabi ;; 1) abi=x86_64 target=x86_64-linux-android echo "X86" > "$llvm/targets_to_build" rusttarget=x86_64 rustup target add x86_64-linux-android ;; 2) abi=arm64-v8a target=aarch64-linux-android echo "AArch64" > "$llvm/targets_to_build" rusttarget=arm64 rustup target add aarch64-linux-android ;; *) echo "Unknown target code in $2." >&2 exit 1 ;; esac sed -i -e "s/include \".*\"/include \"$abi\"/" app/build.gradle # Disable FUS Service or we'll get errors like: # Exception while loading configuration for :app: Could not load the value of field `__buildFusService__` of task `:app:compileFenixReleaseKotlin` of type `org.jetbrains.kotlin.gradle.tasks.KotlinCompile`. echo "kotlin.internal.collectFUSMetrics=false" >> local.properties popd # # Glean # pushd "$glean" echo "rust.targets=linux-x86-64,$rusttarget" >> local.properties localize_maven popd # # Glean for Application Services # pushd "$glean_as" echo "rust.targets=linux-x86-64,$rusttarget" >> local.properties localize_maven popd # # Android Components # pushd "$android_components" find "$patches/a-c-overlay" -type f | while read -r src; do cp "$src" "${src#"$patches/a-c-overlay/"}" done # Add the added search engines as `general` engines sed -i \ -e '/GENERAL_SEARCH_ENGINE_IDS = setOf/a\ "brave",' \ -e '/GENERAL_SEARCH_ENGINE_IDS = setOf/a\ "ddghtml",' \ -e '/GENERAL_SEARCH_ENGINE_IDS = setOf/a\ "ddglite",' \ -e '/GENERAL_SEARCH_ENGINE_IDS = setOf/a\ "metager",' \ -e '/GENERAL_SEARCH_ENGINE_IDS = setOf/a\ "mojeek",' \ -e '/GENERAL_SEARCH_ENGINE_IDS = setOf/a\ "qwantlite",' \ -e '/GENERAL_SEARCH_ENGINE_IDS = setOf/a\ "startpage",' \ components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchEngineReader.kt popd # # UnifiedPush Android Component # pushd "$unifiedpush_ac" localize_maven # Set A-C version echo "mozilla.version=${1%.0}" >> local.properties # Set A-S version sed -i -e 's/0.0.1-SNAPSHOT-+/149.0/' gradle/libs.versions.toml popd # # Application Services # pushd "$application_services" rm -vrf components/remote_settings/dumps/*/attachments/search-config-icons/* find "$patches/a-s-overlay" -type f | while read -r src; do cp "$src" "${src#"$patches/a-s-overlay/"}" done # Remove Mozilla repositories substitution and explicitly add the required ones apply_patch "$patches/a-s-localize_maven.patch" # Configure default search engines apply_patch "$patches/a-s-configure-default-search-engines.patch" # Break the dependency on older A-C sed -i -e '/android-components = /s/"146\.0\.1"/"149.0"/' gradle/libs.versions.toml echo "rust.targets=linux-x86-64,$rusttarget" >> local.properties sed -i -e '/NDK ez-install/,/^$/d' libs/verify-android-ci-environment.sh popd # # WASI SDK # pushd "$wasi" apply_patch "$mozilla_release/taskcluster/scripts/misc/wasi-sdk.patch" popd # # GeckoView # pushd "$mozilla_release" # Remove unneeded dependecies apply_patch "$patches/gecko-dependencies.patch" # Remove Mozilla repositories substitution and explicitly add the required ones apply_patch "$patches/gecko-localize_maven.patch" # Replace GMS with microG client library apply_patch "$patches/gecko-liberate.patch" # Work-around upstream bug to fix compilation with WASI SDK 20, see # https://bugzilla.mozilla.org/show_bug.cgi?id=1994063 apply_patch "$patches/gecko-unbreak-wasi-sdk-20-clang.patch" # Add UnifiedPush support apply_patch "$unifiedpush_ac/patches/a-c-unifiedpush.patch" apply_patch "$unifiedpush_ac/patches/fenix-unifiedpush.patch" # Patch the use of proprietary and tracking libraries apply_patch "$patches/fenix-liberate.patch" # Disable search engines configuration fetching from a Mozilla server apply_patch "$patches/fenix-disable-remote-search-configuration.patch" sed -i 's|https://firefox.settings.services.allizom.org/v1/buckets/main/collections/search-config/records||g' toolkit/components/search/SearchUtils.sys.mjs sed -i 's|https://firefox.settings.services.allizom.org/v1/buckets/main-preview/collections/search-config/records||g' toolkit/components/search/SearchUtils.sys.mjs sed -i 's|https://firefox.settings.services.mozilla.com/v1/buckets/main/collections/search-config/records||g' toolkit/components/search/SearchUtils.sys.mjs sed -i 's|https://firefox.settings.services.mozilla.com/v1/buckets/main-preview/collections/search-config/records||g' toolkit/components/search/SearchUtils.sys.mjs # Remove the use of RemoteSettingsCrashPull, the part of the crash reporter apply_patch "$patches/fenix-disable-crashpull.patch" # Remove "Sent from Firefox" reference on sharing apply_patch "$patches/fenix-disable-sent-from-fx.patch" # Add "Enable UnifiedPush" and "Use UnifiedPush" settings apply_patch "$patches/fenix-use-unifiedpush.patch" # Fail on use of prebuilt binary sed -i 's|https://|hxxps://|' mobile/android/gradle/plugins/nimbus-gradle-plugin/src/main/groovy/org/mozilla/appservices/tooling/nimbus/NimbusGradlePlugin.groovy # Make Nimbus Gradle Plugin use obj/dist/host/bin/nimbus-fml which we copy # there manually from A-S. Otherwise Nimbus Gradle Plugin tries to download # nimbus-fml from Mozilla. sed -i 's/project.gradle.ext.mozconfig.substs.MOZ_APPSERVICES_IN_TREE/true/' mobile/android/gradle/plugins/nimbus-gradle-plugin/src/main/groovy/org/mozilla/appservices/tooling/nimbus/NimbusGradlePlugin.groovy # Fix v125 aar output not including native libraries sed -i \ -e 's/singleVariant("debug")/singleVariant("release")/' \ mobile/android/exoplayer2/build.gradle sed -i \ -e "s/singleVariant('debug')/singleVariant('release')/" \ mobile/android/geckoview/build.gradle # Hack the timeout for # geckoview:generateJNIWrappersForGeneratedWithGeckoBinariesDebug sed -i \ -e 's/max_wait_seconds=600/max_wait_seconds=1800/' \ mobile/android/gradle.py # Patch the LLVM source code # Search clang- in https://android.googlesource.com/platform/ndk/+/refs/tags/ndk-r28b/ndk/toolchains.py LLVM_SVN='530567' python3 "$toolchain_utils/llvm_tools/patch_manager.py" \ --svn_version "$LLVM_SVN" \ --patch_metadata_file "$llvm_android/patches/PATCHES.json" \ --src_path "$llvm" # Fail on use of prebuilt binary sed -i 's|https://github.com|hxxps://github.com|' python/mozboot/mozboot/android.py # Make the build system think we installed the emulator and an AVD mkdir -p "$ANDROID_HOME/emulator" touch "$ANDROID_HOME/emulator/emulator" chmod +x "$ANDROID_HOME/emulator/emulator" mkdir -p "$HOME/.mozbuild/android-device/avd" # Use terser from Debian sed -i \ -e 's|terser_path = terser_dir / ".*"|terser_path = Path("/usr/bin/terser")|' \ python/mozbuild/mozpack/files.py # Configure cat << EOF > mozconfig ac_add_options --disable-crashreporter ac_add_options --disable-debug ac_add_options --disable-tests ac_add_options --disable-updater ac_add_options --enable-application=mobile/android ac_add_options --enable-release ac_add_options --enable-update-channel=release ac_add_options --target=$target ac_add_options --with-android-ndk="$ANDROID_NDK" ac_add_options --with-android-sdk="$ANDROID_SDK" ac_add_options --with-libclang-path="$llvm/out/lib" ac_add_options --with-java-bin-path="/usr/bin" ac_add_options --with-gradle=$(command -v gradle) ac_add_options --with-wasi-sysroot="$wasi/build/install/wasi/share/wasi-sysroot" ac_add_options CC="$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/clang" ac_add_options CXX="$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++" ac_add_options STRIP="$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip" ac_add_options WASM_CC="$wasi/build/install/wasi/bin/clang" ac_add_options WASM_CXX="$wasi/build/install/wasi/bin/clang++" mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj mk_add_options MOZ_MAKE_FLAGS="-j1" export MOZ_REQUIRE_SIGNING= EOF # Disable Gecko Media Plugins and casting sed -i -e '/gmp-provider/d; /casting.enabled/d' mobile/android/app/geckoview-prefs.js cat << EOF >> mobile/android/app/geckoview-prefs.js // Disable Encrypted Media Extensions pref("media.eme.enabled", false); // Disable Gecko Media Plugins pref("media.gmp-provider.enabled", false); // Avoid openh264 being downloaded pref("media.gmp-manager.url.override", "data:text/plain,"); // Disable openh264 if it is already downloaded pref("media.gmp-gmpopenh264.enabled", false); // Disable RemoteSettingsCrashPull pref("browser.crashReports.crashPull", false, locked); pref("browser.crashReports.requestedNeverShowAgain", true, locked); // Disable mandatory extension signing pref("xpinstall.signatures.required", false); // Allow extension installs from any site pref("xpinstall.whitelist.fileRequest", true); pref("extensions.langpacks.signatures.required", false); pref("extensions.experiments.enabled", true); pref("extensions.install.requireBuiltInCerts", false); pref("extensions.webextensions.restrictedDomains", ""); pref("xpinstall.whitelist.required", false); pref("xpinstall.whitelist.directRequest", true); pref("browser.startup.homepage_override.mstone", "ignore"); EOF popd # On cold start with no tabs to restore and no intent URL, open smesh.lol. # Fenix ignores browser.startup.homepage on Android — this is the only way. sed -i '/maybeShowSetAsDefaultBrowserPrompt()$/i\ if (!settings().shouldReturnToBrowser) {\ openToBrowserAndLoad(\ searchTermOrURL = "https:\/\/smesh.lol",\ newTab = true,\ from = BrowserDirection.FromGlobal,\ )\ }' "$fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt"