# Maintainer: aur.chaotic.cx

## options
: ${_build_pgo:=false}     # profile-guided optimization; ~20% better benchmarks, 3x build time
: ${_build_pgo_reuse:=try} # reuse previously generated profile
: ${_build_pgo_xvfb:=true} # use xfvb for profiling, otherwise xwayland-run

: ${_build_lto:=false}        # link-time optimization; may cause spurious errors
: ${_build_system_libs:=true} # use system libraries, reduces build time

: ${_build_limit_cores:=true} # detect usable cores for parallelism, limited by RAM

_pkgname=firefox-nightly
pkgname="$_pkgname"
pkgver=155.0a1+20260805.22+hbb3ac5a21
pkgrel=1
pkgdesc="Fast, Private & Safe Web Browser"
url="https://www.firefox.com/channel/desktop/#nightly"
license=('MPL-2.0')
arch=('x86_64')

depends=(
  dbus
  ffmpeg
  gtk3
  libxss
  libxt
  mime-types
  ttf-font
)
makedepends=(
  cargo
  cbindgen
  clang
  diffutils
  dump_syms
  imake
  jack
  lld
  llvm
  mercurial
  mesa
  nasm
  nodejs
  python
  unzip
  wasi-compiler-rt
  wasi-libc
  wasi-libc++
  wasi-libc++abi
  yasm
  zip
)
optdepends=(
  'hunspell-dictionary: Spell checking'
  'libnotify: Notification integration'
  'networkmanager: Location detection via available WiFi networks'
  'speech-dispatcher: Text-to-Speech'
  'xdg-desktop-portal: Screensharing with Wayland'
)

if [[ "${_build_system_libs::1}" == "t" ]]; then
  depends+=(
    libffi.so          # libffi
    libjpeg.so         # libjpeg-turbo
    libpipewire-0.3.so # libpipewire
    libpixman-1.so     # pixman
    libvpx.so          # libvpx
    libwebp.so         # libwebp
    libwebpdemux.so    # libwebp
    libz.so            # zlib
  )
fi

if [[ "${_build_pgo::1}" == "t" ]]; then
  if [[ "${_build_pgo_xvfb::1}" == "t" ]]; then
    makedepends+=(
      xorg-server-xvfb
    )
  else
    makedepends+=(
      weston
      xorg-xwayland
      wlheadless-run # aur/xwayland-run-git
    )
  fi
fi

options=(
  !debug
  !emptydirs
  !lto
  !makeflags
  !strip
)

_get_version_info() {
  [[ -n "$_pkgver" ]] && return

  local _info_url _filename _response
  _info_url="https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central"
  _filename=$(
    curl -Ssf "$_info_url/" \
      | grep -Po '>\Kfirefox-\S+\.linux-x86_64\.txt(?=<)' \
      | sort -rV | head -1
  )
  _response=$(curl -Ssf "$_info_url/$_filename")

  _version=$(grep -Pom1 'firefox-\K\S+(?=\.en-US)' <<< "$_filename")
  _date=$(sed -E 's&^([0-9]{8})([0-9]*)$&\1.\2&' <<< "$_response" | head -1)
  _revision=$(grep -Pom1 '/rev/\K[a-f0-9]{40}' <<< "$_response")
  _pkgver="${_version:?}+${_date::11}+h${_revision::9}"

  _commit=$(
    curl -Ssf "https://hg-edge.mozilla.org/mozilla-central/rev/$_revision" \
      | grep -Pom1 'git commit.*github.com/\S+/\K[a-f0-9]{40}'
  )
}
_get_version_info

_pkgsrc="firefox-${_commit:?}"
source=(
  "firefox-$_pkgver.tar.gz"::"https://github.com/mozilla-firefox/firefox/archive/$_commit.tar.gz"
  'firefox-nightly-symbolic.svg'
  'firefox-nightly.desktop'
  '0001-Install-under-remoting-name.patch'
)
sha256sums=(
  'SKIP'
  'cb00ea359d6daf37900102307be4f515f1b7ef9c98825c64cc55bb562449d0d8'
  '4304902899987928ea51b7020fb1298b01fa77e327ef66ab00b061f767042b9f'
  '883ca2fa723a7572269d18559d5b82412782ad63e5dd3820eeb0540e3fe34314'
)

pkgver() {
  # set by _get_version_info
  echo "$_pkgver"
}

prepare() {
  mkdir -p mozbuild

  # Google API keys (see http://www.chromium.org/developers/how-tos/api-keys)
  # Note: These are for Arch Linux use ONLY. For your own distribution, please
  # get your own set of keys. Feel free to contact foutrelis@archlinux.org for
  # more information.
  echo -n "AIzaSyDwr302FpOSkGRpLlUpPThNTDPbXcIn_FM" > google-api-key

  cat > mozconfig << END
ac_add_options --enable-application=browser
mk_add_options MOZ_OBJDIR="$srcdir/obj"

ac_add_options --prefix=/usr
ac_add_options --enable-release
ac_add_options --enable-hardening
ac_add_options --enable-rust-simd
ac_add_options --enable-wasm-simd
ac_add_options --enable-linker=lld
ac_add_options --disable-elf-hack
ac_add_options --disable-bootstrap
ac_add_options --with-wasi-sysroot=/usr/share/wasi-sysroot

# Branding
ac_add_options --with-branding=browser/branding/nightly
ac_add_options --enable-update-channel=nightly
ac_add_options --with-distribution-id=org.archlinux
ac_add_options --with-unsigned-addon-scopes=app,system
ac_add_options --allow-addon-sideload
export MOZILLA_OFFICIAL=1
export MOZ_APP_REMOTINGNAME=$_pkgname
export NIGHTLY_BUILD=1
export MOZ_REQUIRE_SIGNING=

# Keys
ac_add_options --with-google-location-service-api-keyfile="$srcdir/google-api-key"
ac_add_options --with-google-safebrowsing-api-keyfile="$srcdir/google-api-key"

# Features
ac_add_options --enable-alsa
ac_add_options --enable-crashreporter
ac_add_options --enable-eme=widevine
ac_add_options --enable-jack
ac_add_options --enable-jxl
ac_add_options --enable-proxy-bypass-protection
ac_add_options --enable-sandbox
ac_add_options --enable-unverified-updates
ac_add_options --enable-webrtc
ac_add_options --disable-default-browser-agent
ac_add_options --disable-parental-controls
ac_add_options --disable-tests
ac_add_options --disable-updater

# Disables Telemetry by Default
mk_add_options MOZ_DATA_REPORTING=0
mk_add_options MOZ_SERVICES_HEALTHREPORT=0
mk_add_options MOZ_TELEMETRY_REPORTING=0

# Debugging
ac_add_options --disable-debug
ac_add_options --disable-debug-symbols
ac_add_options --disable-debug-js-modules
ac_add_options --enable-strip
ac_add_options --enable-install-strip
export STRIP_FLAGS="--strip-debug --strip-unneeded"

# Optimization
ac_add_options --enable-optimize
ac_add_options OPT_LEVEL="2"
ac_add_options RUSTC_OPT_LEVEL="2"

# Other
export AR=llvm-ar
export CC=clang
export CXX=clang++
export NM=llvm-nm
export RANLIB=llvm-ranlib
END

  if [[ "${_build_system_libs::1}" == "t" ]]; then
    cat >> mozconfig << END
# ac_add_options --with-system-av1
# ac_add_options --with-system-icu
# ac_add_options --with-system-libevent
# ac_add_options --with-system-nspr
# ac_add_options --with-system-nss
# ac_add_options --with-system-png
ac_add_options --with-system-ffi
ac_add_options --with-system-gbm
ac_add_options --with-system-jpeg
ac_add_options --with-system-libdrm
ac_add_options --with-system-libvpx
ac_add_options --with-system-pipewire
ac_add_options --with-system-pixman
ac_add_options --with-system-webp
ac_add_options --with-system-zlib
END
  fi

  if [[ "${_build_lto::1}" == "t" ]]; then
    cat >> mozconfig << END
ac_add_options --enable-lto=cross,full
END
  fi

  # build paralleism
  local _mem _nproc _cores
  _mem=$(grep -Pom1 '^MemFree.*\b\K[0-9]+' /proc/meminfo)
  _nproc=$(nproc)

  if [[ "${_build_limit_cores::1}" == "t" ]]; then
    # calculate core availability based on free RAM and CPU count
    _cores=$((_mem / (1024 * 1024) < _nproc ? _mem / (1024 * 1024) : _nproc))
    _cores=$((_cores < 1 ? 1 : _cores))
  elif ((${_build_limit_cores:-0} > 0)); then
    # user-specified, capped by CPU count
    _cores=$((_build_limit_cores > _nproc ? _nproc : _build_limit_cores))
  fi

  if [ -n "${_cores:-}" ]; then
    printf '\nFree RAM: %s\nCores: %s\nUsing: %s\n\n' "$((_mem / (1024 * 1024)))" "$_nproc" "$_cores"
    cat >> mozconfig << END
mk_add_options MOZ_PARALLEL_BUILD=${_cores}
END
  else
    printf '\nFree RAM: %s\nCores: %s\nUsing: auto\n\n' "$((_mem / (1024 * 1024)))" "$_nproc"
  fi

  # apply patches
  local src
  for src in "${source[@]}"; do
    src="${src%%::*}"
    src="${src##*/}"
    src="${src%.zst}"
    if [[ $src == *.patch ]]; then
      printf '\nApplying patch: %s\n' "$src"
      patch -d "$_pkgsrc" -Np1 -F100 -i "${srcdir:?}/$src"
    fi
  done
}

build() (
  export RUSTUP_TOOLCHAIN=stable

  export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-$srcdir/xdg-runtime}"
  [ ! -d "$XDG_RUNTIME_DIR" ] && mkdir -pm700 "${XDG_RUNTIME_DIR:?}"

  export MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE=pip
  export MOZBUILD_STATE_PATH="$srcdir/mozbuild"
  export MOZ_BUILD_DATE="$(date -u${SOURCE_DATE_EPOCH:+d @$SOURCE_DATE_EPOCH} +%Y%m%d%H%M%S)"
  export MOZ_NOSPAM=1

  # Work around https://bugzilla.mozilla.org/show_bug.cgi?id=1969383
  export RUST_MIN_STACK=16777216

  export MOZ_ENABLE_FULL_SYMBOLS=1

  # malloc_usable_size is used in various parts of the codebase
  CFLAGS="${CFLAGS/_FORTIFY_SOURCE=3/_FORTIFY_SOURCE=2}"
  CXXFLAGS="${CXXFLAGS/_FORTIFY_SOURCE=3/_FORTIFY_SOURCE=2}"

  # Breaks compilation since https://bugzilla.mozilla.org/show_bug.cgi?id=1896066
  CFLAGS="${CFLAGS/-fexceptions/}"
  CXXFLAGS="${CXXFLAGS/-fexceptions/}"

  # LTO/PGO needs more open files
  ulimit -n 4096

  cd "$_pkgsrc"

  # Do 3-tier PGO
  if [[ "${_build_pgo::1}" == "t" ]]; then
    local _old_profdata="$SRCDEST/merged.profdata"
    local _old_jarlog="$SRCDEST/jarlog"

    # Restore old profile
    if [[ "${_build_pgo_reuse::1}" == "t" ]]; then
      if [[ -s "$_old_profdata" ]]; then
        echo "Restoring old profile data."
        cp -f "$_old_profdata" merged.profdata
      fi

      if [[ -s "$_old_jarlog" ]]; then
        echo "Restoring old jar log."
        cp -f "$_old_jarlog" jarlog
      fi
    fi

    # Make new profile
    if [[ "${_build_pgo_reuse::1}" != "t" ]] || [[ ! -s merged.profdata ]]; then
      echo "Building instrumented browser..."
      cat > .mozconfig ../mozconfig - << END
ac_add_options --enable-profile-generate=cross
export MOZ_ENABLE_FULL_SYMBOLS=1
END
      ./mach build --priority normal

      echo "Profiling instrumented browser..."
      ./mach package

      local _headless_env=(
        LLVM_PROFDATA=llvm-profdata
        JARLOG_FILE=${PWD@Q}/jarlog
        LIBGL_ALWAYS_SOFTWARE=true
        dbus-run-session
      )

      if [[ "${_build_pgo_xvfb::1}" == "t" ]]; then
        local _headless_run=(
          xvfb-run
          -s "-screen 0 1920x1080x24 -nolisten local"
        )
      else
        local _headless_run=(
          wlheadless-run
          -c weston --width=1920 --height=1080
        )
      fi

      env "${_headless_env[@]}" "${_headless_run[@]}" -- ./mach python build/pgo/profileserver.py

      echo "Removing instrumented browser..."
      ./mach clobber objdir
    fi
  fi

  # Prepare to rebuild
  cat > .mozconfig ../mozconfig

  if [[ -s merged.profdata ]]; then
    stat -c "Profile data found (%s bytes)" merged.profdata
    cat >> .mozconfig - << END
ac_add_options --enable-profile-use=cross
ac_add_options --with-pgo-profile-path=${PWD@Q}/merged.profdata
END

    # save profdata for reuse
    cp -f merged.profdata "$_old_profdata"
  else
    echo "Profile data not found."
  fi

  if [[ -s jarlog ]]; then
    stat -c "Jar log found (%s bytes)" jarlog
    cat >> .mozconfig - << END
ac_add_options --with-pgo-jarlog=${PWD@Q}/jarlog
END

    # save jarlog for reuse
    cp -f jarlog "$_old_jarlog"
  else
    echo "Jar log not found."
  fi

  echo "Building browser..."
  ./mach build --priority normal
)

package() {
  cd "$_pkgsrc"
  DESTDIR="$pkgdir" ./mach install

  local vendorjs="$pkgdir/usr/lib/$_pkgname/browser/defaults/preferences/vendor.js"
  install -Dvm644 /dev/stdin "$vendorjs" << END
// Use LANG environment variable to choose locale
pref("intl.locale.requested", "");

// Use system-provided dictionaries
pref("spellchecker.dictionary_path", "/usr/share/hunspell");

// Disable default browser checking.
pref("browser.shell.checkDefaultBrowser", false);

// Don't disable extensions in the application directory
pref("extensions.autoDisableScopes", 11);

// Enable GNOME Shell search provider
pref("browser.gnome-search-provider.enabled", true);

// Enable JPEG XL images
pref("image.jxl.enabled", true);

// Prevent about:config warning
pref("browser.aboutConfig.showWarning", false);

// Prevent telemetry notification
pref("services.settings.main.search-telemetry-v2.last_check", $(date +%s));
END

  local distini="$pkgdir/usr/lib/$_pkgname/distribution/distribution.ini"
  install -Dvm644 /dev/stdin "$distini" << END
[Global]
id=archlinux
version=1.0
about=Mozilla Firefox for Arch Linux

[Preferences]
app.distributor=archlinux
app.distributor.channel=$_pkgname
app.partner.archlinux=archlinux
END

  local i theme=nightly
  for i in 16 22 24 32 48 64 128 256; do
    install -Dvm644 browser/branding/$theme/default$i.png \
      "$pkgdir/usr/share/icons/hicolor/${i}x${i}/apps/$_pkgname.png"
  done
  install -Dvm644 browser/branding/$theme/content/about-logo.png "$pkgdir/usr/share/icons/hicolor/192x192/apps/$_pkgname.png"
  install -Dvm644 browser/branding/$theme/content/about-logo@2x.png "$pkgdir/usr/share/icons/hicolor/384x384/apps/$_pkgname.png"
  install -Dvm644 browser/branding/$theme/content/about-logo.svg "$pkgdir/usr/share/icons/hicolor/scalable/apps/$_pkgname.svg"
  install -Dvm644 ../$_pkgname-symbolic.svg "$pkgdir/usr/share/icons/hicolor/symbolic/apps/$_pkgname-symbolic.svg"

  install -Dvm644 ../$_pkgname.desktop "$pkgdir/usr/share/applications/$_pkgname.desktop"

  # Install a wrapper to avoid confusion about binary path
  install -Dvm755 /dev/stdin "$pkgdir/usr/bin/$_pkgname" << END
#!/bin/sh
exec /usr/lib/$_pkgname/firefox "\$@"
END

  # Replace duplicate binary with wrapper
  # https://bugzilla.mozilla.org/show_bug.cgi?id=658850
  ln -sfv "$_pkgname" "$pkgdir/usr/lib/$_pkgname/${_pkgname%-*}-bin"

  local sprovider="$pkgdir/usr/share/gnome-shell/search-providers/$_pkgname.search-provider.ini"
  install -Dvm644 /dev/stdin "$sprovider" << END
[Shell Search Provider]
DesktopId=$_pkgname.desktop
BusName=org.mozilla.${_pkgname//-/_}.SearchProvider
ObjectPath=/org/mozilla/${_pkgname//-/_}/SearchProvider
Version=2
END
}
