# Contributor: Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
# Contributor: Ionut Biru <ibiru@archlinux.org>
# Contributor: Jakub Schmidtke <sjakub@gmail.com>
# Maintainer (aur): Figue <ffigue at gmail>
# Contributor: fauno <fauno@kiwwwi.com.ar>
# Contributor: evr <evanroman at gmail>
# Contributor: Muhammad 'MJ' Jassim <UnbreakableMJ@gmail.com>
# Contributor: vando <facundo@esdebian.org>
# Contributor: André Silva <emulatorman@hyperbola.info>
# Contributor: Henry Jensen <hjensen@connochaetos.org>
# Contributor: Luke Shumaker <lukeshu@parabola.nu>
# Contributor: Márcio Silva <coadde@hyperbola.info>
# Maintainer: Andreas Grapentin <andreas@grapentin.org>
# Contributor: bill-auger <bill-auger@programmer.net>
# Contributor: grizzlyuser <grizzlyuser@protonmail.com>


# NOTE: icecat (60.7 < V <= 78.10) are not upstream releases
#       upstream releases would normally have '-gnu' appended to $_upstream_ver
#       this build is based on gnuzilla VCS developement sources
#       rev: b72c22186cf381d7b1f93be550c9da30865d03b4


pkgname=icecat
_upstream_ver=78.10.0-pre2 # -gnu1
pkgver=${_upstream_ver//-/_}
pkgrel=1wip
pkgdesc="the GNU web browser, based on Mozilla Firefox ESR"
arch=(x86_64 i686 armv7h)
license=(MPL GPL LGPL)
url=http://www.gnu.org/software/gnuzilla/
depends=(gtk3 libxt mime-types dbus-glib ffmpeg nss ttf-font libpulse)
makedepends=(m4 unzip zip diffutils python2-setuptools yasm mesa imake inetutils
             xorg-server-xvfb autoconf2.13 rust clang llvm jack gtk2
             python nodejs python2-psutil cbindgen nasm perl-file-rename)
#              python nodejs python2-psutil cbindgen nasm lld perl-file-rename)
# makedepends=(unzip zip diffutils yasm mesa imake inetutils xorg-server-xvfb
#              autoconf2.13 rust clang llvm jack gtk2 nodejs cbindgen nasm
#              python-setuptools python-psutil)
makedepends+=(mozilla-searchplugins jq)
makedepends=(${makedepends[*]/rust/rust=1:1.49.0}) # FIXME:
# [[ "${CARCH}" == 'i686' ]] && makedepends=(${makedepends[*]/llvm/llvm10}) # FIXME: i686 configure fails with LLVM11
                                                                            #        rustup: error while loading shared libraries: libLLVM-10.so
optdepends=('networkmanager: Location detection via available WiFi networks'
            'libnotify: Notification integration'
            'pulseaudio: Audio support'
            'speech-dispatcher: Text-to-Speech'
            'hunspell-en_US: Spell checking, American English')
options=(!emptydirs !makeflags !strip)
source=(https://repo.parabola.nu/other/${pkgname}/${pkgname}-${_upstream_ver}.tar.bz2{,.sig}
        icecat.desktop icecat-safe.desktop
        0001-Use-remoting-name-for-GDK-application-names.patch
        rust_1.48.patch.gz)
source+=(searchplugins_list.json
         9003-misc-libre.patch)
source_i686=('rust-static-disable-network-test-on-static-libraries.patch')
sha256sums=('f4334ab97a30bf8e8fe400c55ed00fcea1d44536dc6df1c7f65fec8eae1664a3'
            'SKIP'
            'e00dbf01803cdd36fd9e1c0c018c19bb6f97e43016ea87062e6134bdc172bc7d'
            '33dd309eeb99ec730c97ba844bf6ce6c7840f7d27da19c82389cdefee8c20208'
            'e0eaec8ddd24bbebf4956563ebc6d7a56f8dada5835975ee4d320dd3d0c9c442'
            'c7f867ccee684939c9f0a9c30ea69127077bbe43af545a03f09dfbbdc02545a9')
sha256sums+=('3edb4add450f94c579f2df7c16ac4d9bd9f5c6acf3fbd8a05ce24c21c317257d'
             '28029afa3201e1be8138be06f741c59d64869edf0c9e90dbb05cfa6b5fff4ecd')
sha256sums_i686=('068efe37a99561490e6ec7b70a3cd4dd84e89e6bdf19f04a475d06c78fd28920')
# validpgpkeys=('318C679D94F17700CC847DE646A70073E4E50D4E') # Ruben Rodriguez
validpgpkeys=('3954A7AB837D0EA9CFA9798925DB7D9B5A8D4B40') # bill-auger (VCS builds)


# PGO requires networking
_should_skip_pgo_armv7h=1 # disable for armv7h - always
_should_skip_pgo_i686=1   # disable for i686   - always
_should_skip_pgo_x86_64=0 # disable for x86_64 - libremakepkg
eval "_should_skip_pgo=\$_should_skip_pgo_${CARCH}"


_check_build_config() {
  pushd "${srcdir}"/${pkgname}-${pkgver%_*} > /dev/null

  echo "Checking build configuration..."

  # Configure produces mozinfo.json that reflects current configuration.
  # See build/docs/mozinfo.rst
  ./mach configure

  # In this test, jq collects values of the following keys of mozinfo.json into array,
  # and checks if any of them are not equal to false, in which case it returns "true".
  # E.g. if the value of any key is true or null (in case the key is missing from mozinfo.json),
  # that means the build configuration has to be reworked.
  local obj_directory=$(./mach environment | sed -En '/object directory:/{n;s/^\s+//;p;}')
  local mozinfo_json="${obj_directory}"/mozinfo.json
  local antifeature_keys=('.crashreporter' '.datareporting' '.healthreport' '.normandy' '.telemetry' '.updater')
  local antifeatures=()
  local jq_cmd=( jq -e "${key} != false" "${mozinfo_json}" )

  printf  "\$mozinfo_json %s - obj_directory is: %s\n"            \
          "$( [[ -f "${mozinfo_json}" ]] || printf "not " )found" \
          "${obj_directory}"

  for key in ${antifeature_keys[@]} ; do ${jq_cmd[@]} && antifeatures+=(${key}); done ;

  if   (( ${#antifeatures[@]} ))
  then echo "Some anti-features are not disabled in build configuration files, aborting:"
       for key in ${antifeature_keys[@]}
       do  echo "${key} - $( ${jq_cmd[@]} || echo "not " )detected\n"
       done

       return 1 # FIXME: .datareporting is detected
  fi

  popd > /dev/null
}

prepare() {
  mkdir -p mozbuild
  cd "$srcdir/$pkgname-${pkgver%_*}"

  # https://bugzilla.mozilla.org/show_bug.cgi?id=1530052
  patch -Np1 -i ../0001-Use-remoting-name-for-GDK-application-names.patch

  # https://bugzilla.mozilla.org/show_bug.cgi?id=1667736
  patch -Np1 -i ../rust_1.48.patch

  cat >../mozconfig <<END
ac_add_options --enable-application=browser

ac_add_options --prefix=/usr
ac_add_options --enable-release
ac_add_options --enable-hardening
ac_add_options --enable-optimize
ac_add_options --enable-rust-simd
export CC='clang --target=x86_64-unknown-linux-gnu'
export CXX='clang++ --target=x86_64-unknown-linux-gnu'
export AR=llvm-ar
export NM=llvm-nm
export RANLIB=llvm-ranlib

# Branding
ac_add_options --enable-official-branding
ac_add_options --enable-update-channel=release
ac_add_options --with-distribution-id=nu.parabola
ac_add_options --with-unsigned-addon-scopes=app,system
ac_add_options --allow-addon-sideload
export MOZ_APP_NAME=${pkgname}
export MOZ_APP_REMOTINGNAME=${pkgname}
export MOZ_TELEMETRY_REPORTING=
export MOZ_REQUIRE_SIGNING=
ac_add_options --with-app-basename=${pkgname}
ac_add_options --with-app-name=${pkgname}

# System libraries
ac_add_options --with-system-nspr
ac_add_options --with-system-nss

# Features
ac_add_options --enable-alsa
ac_add_options --enable-jack
ac_add_options --disable-crashreporter
ac_add_options --disable-updater
ac_add_options --disable-tests
ac_add_options --disable-eme
END


  ## [ARCH-SPECIFIC CONFIG] ##

  case "${CARCH}" in
  armv7h)
# TODO: re-work for armv7h
#    sed -i '/--enable-linker=gold/d' ../mozconfig
#    sed -i '/--enable-rust-simd/d' ../mozconfig
#
#    # https://bugzilla.mozilla.org/show_bug.cgi?id=1463035
#    patch -Np1 -i "$srcdir"/mozilla-1463035.patch
#
#    cat >> ../mozconfig <<END
#ac_add_options --enable-optimize="-g -O2 -fno-schedule-insns"
#ac_add_options --disable-elf-hack
#ac_add_options --disable-webrtc
#ac_add_options --disable-av1
#END
    ;;
  i686)
#    sed -i '/--enable-linker=gold/d' ../mozconfig
    sed -i '/--enable-rust-simd/d' ../mozconfig

    # test failure in rust code (complaining about network functions) when PGO is used,
    #   TEST-UNEXPECTED-FAIL | check_networking | libgkrust.a | Identified 7 networking function(s) being imported in the rust static library (accept,connect,getsockname,getsockopt,listen,recv,send)
    # see https://bugzilla.mozilla.org/show_bug.cgi?id=1565757
    echo "applying rust-static-disable-network-test-on-static-libraries.patch"
    patch -Np0 -i ../rust-static-disable-network-test-on-static-libraries.patch
    ;;
  x86_64)
    ;;
  *) echo "no [ARCH-SPECIFIC CONFIG] for arch: ${CARCH}" ; return 1 ;
    ;;
  esac


  ## searchengines ##

  pushd browser/components/search/extensions > /dev/null

  # Patch search-engines configs
  cp "${srcdir}"/searchplugins_list.json list.json
  sed -i 's|https://duckduckgo.com/|https://html.duckduckgo.com/html/|' ddg/manifest.json

  # Removing URL parameters that let DuckDuckGo know the place in UI
  # the search was ran from (like address bar, context menu, etc.)
  local jq_cmd='del(.chrome_settings_overrides.search_provider.params)'
  jq "${jq_cmd}" ddg/manifest.json > manifest.json.tmp
  ! diff manifest.json.tmp ddg/manifest.json > /dev/null
  mv manifest.json.tmp ddg/manifest.json

  # Delete unused search engine configs
  cp -rv /usr/share/mozilla/searchplugins/* .
  find -mindepth 1 -maxdepth 1      \
       -not -name ddg               \
       -not -name duckduckgo-html   \
       -not -name duckduckgo-lite   \
       -not -name internet-archive  \
       -not -name parabola-labs     \
       -not -name parabola-packages \
       -not -name parabola-wiki     \
       -not -name searx             \
       -not -name wikipedia         \
       -not -name yacy              \
       -not -name list.json         \
       -exec rm -rf {} \;

  # Sanity-check search-engines patching
  local engines_err_msg="search-engines patching needs re-working"
  jq < list.json || ! echo "${engines_err_msg}"

  popd > /dev/null


  ## libre patching ##

  # Remove remaining non-free bits
  echo "applying 9003-misc-libre.patch"
  patch -Np1 --no-backup-if-mismatch -i "${srcdir}"/9003-misc-libre.patch
}

build() {
  cd "$srcdir/$pkgname-${pkgver%_*}"

  ## build env ##

  export MOZ_NOSPAM=1
  export MOZBUILD_STATE_PATH="$srcdir/mozbuild"
  export MACH_USE_SYSTEM_PYTHON=1

  # LTO needs more open files
  ulimit -n 4096

  # clang-{9,10,11} -> error: unknown argument: '-fvar-tracking-assignments'
  CFLAGS="${CFLAGS/-fvar-tracking-assignments/}"
  CXXFLAGS="${CXXFLAGS/-fvar-tracking-assignments/}"


  ## [ARCH-SPECIFIC BUILD ENV] ##

  case "${CARCH}" in
    armv7h)
# TODO: re-work for armv7h
#       export RUSTFLAGS+=" -Cdebuginfo=0 -Clto=off"
#       export LDFLAGS+=" -Wl,--no-keep-memory -Wl,--reduce-memory-overheads"
      ;;
    i686)
      # -fno-plt with cross-LTO -> LLVM ERROR: Function Import: link error
      CFLAGS="${CFLAGS/-fno-plt/}"
      CXXFLAGS="${CXXFLAGS/-fno-plt/}"

      # disable LTO (clang has issues on IA32)
      export RUSTFLAGS+=" -Cdebuginfo=0 -Clto=off"
      export LDFLAGS+=" -Wl,--no-keep-memory -Wl,--reduce-memory-overheads"
      ;;
    x86_64)
      # TODO: this may only be needed for v78
      # -fno-plt with cross-LTO causes obscure LLVM errors
      # LLVM ERROR: Function Import: link error
#      CFLAGS="${CFLAGS/-fno-plt/}"
#      CXXFLAGS="${CXXFLAGS/-fno-plt/}"
      ;;
    *) echo "no [ARCH-SPECIFIC BUILD ENV] for arch: ${CARCH}" ; return 1 ;
      ;;
  esac
  export CFLAGS
  export CXXFLAGS


  ## [ARCH-SPECIFIC BUILD CONFIG] ##

  case ${CARCH} in
  armv7h)
# TODO: re-work for armv7h
    ;;
  i686)
    # avoid excessive debug symbols in rust leading to out-of-memory situations
    sed -i "s/debug_info = '\''2'\''/debug_info = '\''0'\''/" build/moz.configure/toolchain.configure
    ;;
  x86_64)
    ;;
  *) echo "no [ARCH-SPECIFIC BUILD CONFIG] for arch: ${CARCH}" ; return 1 ;
    ;;
  esac


  ## PGO build ##

  if (( $_should_skip_pgo ))
  then
    # skipping "3-tier PGO" "instrumented browser", to avoid OOM problems;
    # so we have the final .mozconfig now
    cp ../mozconfig .mozconfig
  else
    # Do 3-tier PGO
    echo "Building instrumented browser..."
    cat >.mozconfig ../mozconfig - <<END
ac_add_options --enable-profile-generate=cross
END
    _check_build_config
    ./mach build

    echo "Profiling instrumented browser..."
    ./mach package
    LLVM_PROFDATA=llvm-profdata \
      JARLOG_FILE="$PWD/jarlog" \
      xvfb-run -s "-screen 0 1920x1080x24 -nolisten local" \
      ./mach python build/pgo/profileserver.py

    if [[ ! -s merged.profdata ]]; then
      echo "No profile data produced."
      return 1
    fi

    if [[ ! -s jarlog ]]; then
      echo "No jar log produced."
      return 1
    fi

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

  cat >.mozconfig ../mozconfig - <<END
ac_add_options --enable-lto=cross
ac_add_options --enable-profile-use=cross
ac_add_options --with-pgo-profile-path=${PWD@Q}/merged.profdata
ac_add_options --with-pgo-jarlog=${PWD@Q}/jarlog
END
  fi # $_should_skip_pgo


  ## sanity checks ##

  # each of the [ARCH-SPECIFIC BUILD CONFIG] branches above should have created .mozconfig
  [[ ! -f .mozconfig ]] && echo ".mozconfig file not found in source root" && return 1
  _check_build_config


  ## main build ##

  echo "Building optimized browser..."
  ./mach build
}

package() {
  cd "$srcdir/$pkgname-${pkgver%_*}"
  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);
END

  local distini="$pkgdir/usr/lib/$pkgname/distribution/distribution.ini"
  install -Dvm644 /dev/stdin "$distini" <<END
[Global]
id=parabola
version=1.0
about=Icecat for Parabola GNU/Linux-libre

[Preferences]
app.distributor=parabola
app.distributor.channel=$pkgname
app.partner.parabola=parabola
END

  install -m755 -d ${pkgdir}/usr/share/applications
  install -m755 -d ${pkgdir}/usr/share/pixmaps

  local i
  for i in 16 32 48; do
    install -Dm644 browser/branding/official/default${i}.png \
      "$pkgdir/usr/share/icons/hicolor/${i}x${i}/apps/${pkgname}.png"
  done

  install -Dm644 browser/branding/official/default48.png "${pkgdir}"/usr/share/pixmaps/icecat.png
  install -Dm644 "${srcdir}"/icecat.desktop "${pkgdir}"/usr/share/applications/
  install -Dm644 "${srcdir}"/icecat-safe.desktop "${pkgdir}"/usr/share/applications/

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


  ## [ARCH-SPECIFIC INSTALL] ##

  case ${CARCH} in
    armv7h)
# TODO: re-work for armv7h
    ;;
    i686)
      # libxul.so cannot find it's libraries
#       install -dm 755 "${pkgdir}"/etc/ld.so.conf.d
#       echo "/usr/lib/${pkgname}" > "${pkgdir}"/etc/ld.so.conf.d/${pkgname}.conf
    ;;
    x86_64)
    ;;
    *) echo "no [ARCH-SPECIFIC INSTALL] for arch: ${CARCH}" ; return 1 ;
    ;;
  esac

  # Replace duplicate binary with wrapper
  # https://bugzilla.mozilla.org/show_bug.cgi?id=658850
  ln -srfv "$pkgdir/usr/bin/$pkgname" "$pkgdir/usr/lib/$pkgname/$pkgname-bin"

  # Use system certificates
  local nssckbi="$pkgdir/usr/lib/$pkgname/libnssckbi.so"
  if [[ -e $nssckbi ]]; then
    ln -srfv "$pkgdir/usr/lib/libnssckbi.so" "$nssckbi"
  fi
}
