mirror of
https://github.com/InstanceBrick/nightcap.git
synced 2026-10-17 17:00:55 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9cedf389a7 | ||
|
|
bbe454641b | ||
|
|
097f782694 | ||
|
|
2a154b6f58 | ||
|
|
0b8cbef447 | ||
|
|
f1d4a05051 | ||
|
|
f4e9349f46 | ||
|
|
63070b6462 | ||
|
|
fb5f38cb40 | ||
|
|
fa370b9dbb | ||
|
|
9bdd737d10 | ||
|
|
df253e786f | ||
|
|
53cd79b7da | ||
|
|
febebef554 | ||
|
|
23fe2eeca5 | ||
|
|
6f5de3a31d | ||
|
|
ea5929faf6 | ||
|
|
220c083e83 | ||
|
|
d778a5bc8a | ||
|
|
0a039628db | ||
|
|
b40fd5d2d6 | ||
|
|
5fb44c66e6 | ||
|
|
5d636749fa | ||
|
|
88b7382577 | ||
|
|
3ce39c1f39 | ||
|
|
6aa22c257d | ||
|
|
e5cf5e3de4 | ||
|
|
36733cfb75 | ||
|
|
ca760f111b | ||
|
|
bfb27b4104 | ||
|
|
5663fe7d25 |
No files matched your search
@@ -1,3 +1,4 @@
|
||||
# Preserve exact upstream whitespace in the provenance-locked Android core
|
||||
# snapshot. Local Mocktail sources remain subject to git diff --check.
|
||||
third_party/mcpelauncher-linker/core/** -whitespace
|
||||
packaging/freebsd/*.patch -whitespace
|
||||
@@ -0,0 +1,104 @@
|
||||
name: Publish AUR development package
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: aur-mocktail-git
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish mocktail-git
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Check out source
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Prepare AUR metadata
|
||||
shell: bash
|
||||
run: |
|
||||
set -Eeuo pipefail
|
||||
package_dir="$GITHUB_WORKSPACE/packaging/aur/mocktail-git"
|
||||
version="$(sed -n \
|
||||
's/^[[:space:]]*VERSION[[:space:]]\+\([0-9][0-9.]*\).*/\1/p' \
|
||||
CMakeLists.txt | head -n 1)"
|
||||
[[ "$version" =~ ^[0-9]+(\.[0-9]+)*$ ]]
|
||||
pkgver="${version}.r$(git rev-list --count HEAD).g$(git rev-parse --short=7 HEAD)"
|
||||
sed -i "s/^pkgver=.*/pkgver=${pkgver}/" "$package_dir/PKGBUILD"
|
||||
|
||||
docker run --rm \
|
||||
--volume "$package_dir:/pkg" \
|
||||
archlinux:base-devel bash -Eeuo pipefail -c '
|
||||
useradd --create-home builder
|
||||
install -d -o builder -g builder /tmp/mocktail-git
|
||||
install -o builder -g builder -m 0644 \
|
||||
/pkg/PKGBUILD /tmp/mocktail-git/PKGBUILD
|
||||
runuser -u builder -- bash -c \
|
||||
"cd /tmp/mocktail-git && makepkg --printsrcinfo" \
|
||||
> /pkg/.SRCINFO
|
||||
'
|
||||
|
||||
grep -Fqx "pkgver=${pkgver}" "$package_dir/PKGBUILD"
|
||||
grep -Fqx $'\tpkgver = '"${pkgver}" "$package_dir/.SRCINFO"
|
||||
printf 'AUR_PKGVER=%s\n' "$pkgver" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Publish to the AUR
|
||||
shell: bash
|
||||
env:
|
||||
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
||||
AUR_SSH_KEY_PASSPHRASE: ${{ secrets.AUR_SSH_KEY_PASSPHRASE }}
|
||||
run: |
|
||||
set -Eeuo pipefail
|
||||
[[ -n "$AUR_SSH_PRIVATE_KEY" ]]
|
||||
[[ -n "$AUR_SSH_KEY_PASSPHRASE" ]]
|
||||
|
||||
private_key="$RUNNER_TEMP/aur_ed25519"
|
||||
askpass="$RUNNER_TEMP/aur_askpass"
|
||||
known_hosts="$RUNNER_TEMP/aur_known_hosts"
|
||||
printf '%s\n' "$AUR_SSH_PRIVATE_KEY" > "$private_key"
|
||||
unset AUR_SSH_PRIVATE_KEY
|
||||
chmod 0600 "$private_key"
|
||||
printf '%s\n' \
|
||||
'#!/usr/bin/env bash' \
|
||||
'printf '\''%s\n'\'' "$AUR_SSH_KEY_PASSPHRASE"' \
|
||||
> "$askpass"
|
||||
chmod 0700 "$askpass"
|
||||
eval "$(ssh-agent -s)"
|
||||
trap 'ssh-agent -k >/dev/null; rm -f -- "$private_key" "$askpass"' EXIT
|
||||
DISPLAY=:0 SSH_ASKPASS="$askpass" SSH_ASKPASS_REQUIRE=force \
|
||||
ssh-add "$private_key" </dev/null
|
||||
unset AUR_SSH_KEY_PASSPHRASE
|
||||
|
||||
ssh-keyscan -T 10 -t ed25519 aur.archlinux.org > "$known_hosts"
|
||||
fingerprint="$(ssh-keygen -lf "$known_hosts" -E sha256 | awk '{print $2}')"
|
||||
[[ "$fingerprint" == \
|
||||
'SHA256:RFzBCUItH9LZS0cKB5UE6ceAYhBD5C8GeOBip8Z11+4' ]]
|
||||
|
||||
export GIT_SSH_COMMAND="ssh -F /dev/null -i $private_key \
|
||||
-o BatchMode=yes -o IdentitiesOnly=yes \
|
||||
-o StrictHostKeyChecking=yes \
|
||||
-o UserKnownHostsFile=$known_hosts"
|
||||
aur_dir="$RUNNER_TEMP/mocktail-git-aur"
|
||||
git clone --branch master --single-branch \
|
||||
ssh://aur@aur.archlinux.org/mocktail-git.git "$aur_dir"
|
||||
install -m 0644 packaging/aur/mocktail-git/PKGBUILD "$aur_dir/PKGBUILD"
|
||||
install -m 0644 packaging/aur/mocktail-git/.SRCINFO "$aur_dir/.SRCINFO"
|
||||
|
||||
git -C "$aur_dir" config user.name komaruworld
|
||||
git -C "$aur_dir" config user.email rtysus228@gmail.com
|
||||
git -C "$aur_dir" add PKGBUILD .SRCINFO
|
||||
if git -C "$aur_dir" diff --cached --quiet; then
|
||||
printf 'mocktail-git %s is already published\n' "$AUR_PKGVER"
|
||||
exit 0
|
||||
fi
|
||||
git -C "$aur_dir" commit -m "Update to ${AUR_PKGVER}"
|
||||
git -C "$aur_dir" push origin HEAD:master
|
||||
+20
-115
@@ -3,7 +3,27 @@ name: CI
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- '.github/workflows/**'
|
||||
- 'CMakeLists.txt'
|
||||
- 'Makefile'
|
||||
- 'README.md'
|
||||
- 'config/**'
|
||||
- 'packaging/**'
|
||||
- 'scripts/**'
|
||||
- 'stubs/**'
|
||||
- 'tests/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/**'
|
||||
- 'CMakeLists.txt'
|
||||
- 'Makefile'
|
||||
- 'README.md'
|
||||
- 'config/**'
|
||||
- 'packaging/**'
|
||||
- 'scripts/**'
|
||||
- 'stubs/**'
|
||||
- 'tests/**'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
@@ -38,118 +58,3 @@ jobs:
|
||||
bash tests/managed_payload_build_contract_test.sh .
|
||||
bash tests/flatpak_packaging_test.sh .
|
||||
bash tests/native_packaging_test.sh .
|
||||
|
||||
flatpak:
|
||||
name: Flatpak build
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- name: Check out source
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
- name: Install Flatpak builder
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes flatpak flatpak-builder gnupg
|
||||
flatpak remote-add --user --if-not-exists flathub \
|
||||
https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||
|
||||
- name: Build Flatpak repository and bundle
|
||||
shell: bash
|
||||
env:
|
||||
FLATPAK_GPG_PRIVATE_KEY: ${{ secrets.FLATPAK_GPG_PRIVATE_KEY }}
|
||||
FLATPAK_GPG_KEY_ID: ${{ secrets.FLATPAK_GPG_KEY_ID }}
|
||||
run: |
|
||||
set -Eeuo pipefail
|
||||
git update-ref refs/heads/main "$GITHUB_SHA"
|
||||
builder_signing=()
|
||||
bundle_keys=()
|
||||
publish=false
|
||||
if [[ "$GITHUB_REF" == refs/heads/main && \
|
||||
"$GITHUB_EVENT_NAME" != pull_request ]]; then
|
||||
publish=true
|
||||
[[ -n "$FLATPAK_GPG_PRIVATE_KEY" && \
|
||||
-n "$FLATPAK_GPG_KEY_ID" ]]
|
||||
install -d -m 0700 "$RUNNER_TEMP/mocktail-gnupg"
|
||||
printf '%s' "$FLATPAK_GPG_PRIVATE_KEY" | \
|
||||
gpg --batch --homedir "$RUNNER_TEMP/mocktail-gnupg" --import
|
||||
gpg --batch --homedir "$RUNNER_TEMP/mocktail-gnupg" \
|
||||
--export "$FLATPAK_GPG_KEY_ID" >mocktail-flatpak.gpg
|
||||
builder_signing=(
|
||||
"--gpg-sign=$FLATPAK_GPG_KEY_ID"
|
||||
"--gpg-homedir=$RUNNER_TEMP/mocktail-gnupg"
|
||||
)
|
||||
bundle_keys=(--gpg-keys=mocktail-flatpak.gpg)
|
||||
fi
|
||||
flatpak-builder \
|
||||
--arch=x86_64 \
|
||||
--jobs=4 \
|
||||
--user \
|
||||
--install-deps-from=flathub \
|
||||
--disable-rofiles-fuse \
|
||||
--force-clean \
|
||||
--default-branch=stable \
|
||||
--repo=repo \
|
||||
"${builder_signing[@]}" \
|
||||
build-flatpak-ci \
|
||||
packaging/flatpak/space.bigrat.mocktail.json
|
||||
if [[ "$publish" == true ]]; then
|
||||
flatpak build-update-repo \
|
||||
--generate-static-deltas \
|
||||
--static-delta-jobs=2 \
|
||||
--prune \
|
||||
--gpg-sign="$FLATPAK_GPG_KEY_ID" \
|
||||
--gpg-homedir="$RUNNER_TEMP/mocktail-gnupg" \
|
||||
repo
|
||||
fi
|
||||
flatpak build-bundle \
|
||||
--arch=x86_64 \
|
||||
"${bundle_keys[@]}" \
|
||||
repo \
|
||||
Mocktail-x86_64.flatpak \
|
||||
space.bigrat.mocktail \
|
||||
stable
|
||||
if [[ "$publish" == true ]]; then
|
||||
./scripts/assemble_flatpak_pages.sh \
|
||||
repo Mocktail-x86_64.flatpak mocktail-flatpak.gpg public
|
||||
fi
|
||||
|
||||
- name: Upload Flatpak
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: Mocktail-x86_64-flatpak
|
||||
path: Mocktail-x86_64.flatpak
|
||||
if-no-files-found: error
|
||||
retention-days: 14
|
||||
|
||||
- name: Configure GitHub Pages
|
||||
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
|
||||
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
|
||||
|
||||
- name: Upload GitHub Pages repository
|
||||
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
|
||||
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
||||
with:
|
||||
path: public
|
||||
|
||||
deploy-pages:
|
||||
name: Publish Flatpak repository
|
||||
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
|
||||
needs: flatpak
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- name: Deploy GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
|
||||
@@ -0,0 +1,193 @@
|
||||
name: Flatpak
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [Native packages]
|
||||
types: [completed]
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/flatpak.yml'
|
||||
- '.gitmodules'
|
||||
- 'CMakeLists.txt'
|
||||
- 'LICENSE'
|
||||
- 'assets/screenshots/**'
|
||||
- 'cmake/**'
|
||||
- 'config/**'
|
||||
- 'include/**'
|
||||
- 'packaging/flatpak/**'
|
||||
- 'packaging/discord-join.html'
|
||||
- 'packaging/icons/**'
|
||||
- 'packaging/space.bigrat.mocktail.desktop'
|
||||
- 'packaging/space.bigrat.mocktail.metainfo.xml'
|
||||
- 'packaging/space.bigrat.mocktail.svg'
|
||||
- 'scripts/assemble_flatpak_pages.sh'
|
||||
- 'scripts/assemble_native_repositories.sh'
|
||||
- 'site/**'
|
||||
- 'src/**'
|
||||
- 'stubs/**'
|
||||
- 'third_party/**'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: flatpak-${{ github.event.workflow_run.head_sha || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
flatpak:
|
||||
name: Flatpak build
|
||||
if: >-
|
||||
github.event_name != 'workflow_run' ||
|
||||
(github.event.workflow_run.conclusion == 'success' &&
|
||||
github.event.workflow_run.event != 'pull_request' &&
|
||||
github.event.workflow_run.head_branch == 'main')
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 120
|
||||
env:
|
||||
MOCKTAIL_PUBLISH: ${{ (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event != 'pull_request' && github.event.workflow_run.head_branch == 'main') || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') }}
|
||||
MOCKTAIL_SOURCE_SHA: ${{ github.event.workflow_run.head_sha || github.sha }}
|
||||
steps:
|
||||
- name: Check out source
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
|
||||
submodules: recursive
|
||||
|
||||
- name: Download package repositories
|
||||
if: env.MOCKTAIL_PUBLISH == 'true'
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -Eeuo pipefail
|
||||
run_id="${{ github.event.workflow_run.id }}"
|
||||
if [[ -z "$run_id" ]]; then
|
||||
run_id="$(gh run list \
|
||||
--workflow packages.yml \
|
||||
--branch main \
|
||||
--event push \
|
||||
--status success \
|
||||
--limit 1 \
|
||||
--json databaseId \
|
||||
--jq '.[0].databaseId')"
|
||||
fi
|
||||
[[ -n "$run_id" ]]
|
||||
gh run download "$run_id" \
|
||||
--name Mocktail-native-repositories \
|
||||
--dir native-repositories
|
||||
[[ -d native-repositories/apt && \
|
||||
-d native-repositories/rpm && \
|
||||
-d native-repositories/downloads && \
|
||||
-s native-repositories/mocktail-packages.gpg ]]
|
||||
|
||||
- name: Install Flatpak builder
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes flatpak flatpak-builder gnupg
|
||||
flatpak remote-add --user --if-not-exists flathub \
|
||||
https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||
|
||||
- name: Build Flatpak repository and bundle
|
||||
shell: bash
|
||||
env:
|
||||
FLATPAK_GPG_PRIVATE_KEY: ${{ secrets.FLATPAK_GPG_PRIVATE_KEY }}
|
||||
FLATPAK_GPG_KEY_ID: ${{ secrets.FLATPAK_GPG_KEY_ID }}
|
||||
run: |
|
||||
set -Eeuo pipefail
|
||||
git update-ref refs/heads/main "$MOCKTAIL_SOURCE_SHA"
|
||||
builder_signing=()
|
||||
bundle_keys=()
|
||||
if [[ "$MOCKTAIL_PUBLISH" == true ]]; then
|
||||
[[ -n "$FLATPAK_GPG_PRIVATE_KEY" && \
|
||||
-n "$FLATPAK_GPG_KEY_ID" ]]
|
||||
install -d -m 0700 "$RUNNER_TEMP/mocktail-gnupg"
|
||||
printf '%s' "$FLATPAK_GPG_PRIVATE_KEY" | \
|
||||
gpg --batch --homedir "$RUNNER_TEMP/mocktail-gnupg" --import
|
||||
gpg --batch --homedir "$RUNNER_TEMP/mocktail-gnupg" \
|
||||
--export "$FLATPAK_GPG_KEY_ID" >mocktail-flatpak.gpg
|
||||
builder_signing=(
|
||||
"--gpg-sign=$FLATPAK_GPG_KEY_ID"
|
||||
"--gpg-homedir=$RUNNER_TEMP/mocktail-gnupg"
|
||||
)
|
||||
bundle_keys=(--gpg-keys=mocktail-flatpak.gpg)
|
||||
fi
|
||||
flatpak-builder \
|
||||
--arch=x86_64 \
|
||||
--jobs=4 \
|
||||
--user \
|
||||
--install-deps-from=flathub \
|
||||
--disable-rofiles-fuse \
|
||||
--force-clean \
|
||||
--default-branch=stable \
|
||||
--repo=repo \
|
||||
"${builder_signing[@]}" \
|
||||
build-flatpak-ci \
|
||||
packaging/flatpak/space.bigrat.mocktail.json
|
||||
if [[ "$MOCKTAIL_PUBLISH" == true ]]; then
|
||||
flatpak build-update-repo \
|
||||
--generate-static-deltas \
|
||||
--static-delta-jobs=2 \
|
||||
--prune \
|
||||
--gpg-sign="$FLATPAK_GPG_KEY_ID" \
|
||||
--gpg-homedir="$RUNNER_TEMP/mocktail-gnupg" \
|
||||
repo
|
||||
fi
|
||||
flatpak build-bundle \
|
||||
--arch=x86_64 \
|
||||
"${bundle_keys[@]}" \
|
||||
repo \
|
||||
Mocktail-x86_64.flatpak \
|
||||
space.bigrat.mocktail \
|
||||
stable
|
||||
if [[ "$MOCKTAIL_PUBLISH" == true ]]; then
|
||||
./scripts/assemble_flatpak_pages.sh \
|
||||
repo Mocktail-x86_64.flatpak mocktail-flatpak.gpg \
|
||||
public native-repositories
|
||||
fi
|
||||
|
||||
- name: Upload Flatpak
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: Mocktail-x86_64-flatpak
|
||||
path: Mocktail-x86_64.flatpak
|
||||
if-no-files-found: error
|
||||
retention-days: 14
|
||||
|
||||
- name: Configure GitHub Pages
|
||||
if: env.MOCKTAIL_PUBLISH == 'true'
|
||||
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
|
||||
|
||||
- name: Upload GitHub Pages repository
|
||||
if: env.MOCKTAIL_PUBLISH == 'true'
|
||||
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
||||
with:
|
||||
path: public
|
||||
|
||||
deploy-pages:
|
||||
name: Publish Flatpak repository
|
||||
if: >-
|
||||
(github.event_name == 'workflow_run' &&
|
||||
github.event.workflow_run.conclusion == 'success' &&
|
||||
github.event.workflow_run.event != 'pull_request' &&
|
||||
github.event.workflow_run.head_branch == 'main') ||
|
||||
(github.event_name == 'workflow_dispatch' &&
|
||||
github.ref == 'refs/heads/main')
|
||||
needs: flatpak
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- name: Deploy GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
|
||||
@@ -3,7 +3,25 @@ name: Native packages
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths-ignore:
|
||||
- '.github/workflows/ci.yml'
|
||||
- '.gitignore'
|
||||
- 'README.md'
|
||||
- 'assets/screenshots/**'
|
||||
- 'docs/**'
|
||||
- 'packaging/aur/**'
|
||||
- 'scripts/build_flatpak.sh'
|
||||
- 'tests/**'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '.github/workflows/ci.yml'
|
||||
- '.gitignore'
|
||||
- 'README.md'
|
||||
- 'assets/screenshots/**'
|
||||
- 'docs/**'
|
||||
- 'packaging/aur/**'
|
||||
- 'scripts/build_flatpak.sh'
|
||||
- 'tests/**'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
@@ -35,7 +53,7 @@ jobs:
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update
|
||||
apt-get install --yes --no-install-recommends \
|
||||
build-essential cmake git ninja-build pkg-config \
|
||||
build-essential cmake git ninja-build pkg-config lld \
|
||||
libsdl3-dev libsdl3-ttf-dev libcurl4-openssl-dev \
|
||||
libssl-dev nlohmann-json3-dev libyaml-dev libelf-dev \
|
||||
libminizip-dev libcapstone-dev libgtk-4-dev \
|
||||
@@ -97,14 +115,16 @@ jobs:
|
||||
- name: Build DEB
|
||||
shell: bash
|
||||
run: |
|
||||
nightly_suffix=".nightly.$(git show -s --format=%cd --date=format:%Y%m%d%H%M%S "$GITHUB_SHA").g${GITHUB_SHA:0:8}"
|
||||
docker run --rm \
|
||||
--volume "$GITHUB_WORKSPACE:/workspace" \
|
||||
--workdir /workspace \
|
||||
--env MOCKTAIL_PACKAGE_VERSION_SUFFIX="$nightly_suffix" \
|
||||
ubuntu:26.04 bash -Eeuo pipefail -c '
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update
|
||||
apt-get install --yes --no-install-recommends \
|
||||
build-essential cmake git ninja-build pkg-config fakeroot \
|
||||
build-essential cmake git ninja-build pkg-config lld fakeroot \
|
||||
dpkg-dev file libsdl3-dev libsdl3-ttf-dev \
|
||||
libcurl4-openssl-dev libssl-dev nlohmann-json3-dev \
|
||||
libyaml-dev libelf-dev libminizip-dev libcapstone-dev \
|
||||
@@ -114,6 +134,8 @@ jobs:
|
||||
cmake -S . -B build-deb -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DMOCKTAIL_PACKAGE_NAME=mocktail-nightly \
|
||||
-DMOCKTAIL_PACKAGE_VERSION_SUFFIX="$MOCKTAIL_PACKAGE_VERSION_SUFFIX" \
|
||||
-DBUILD_TESTING=OFF
|
||||
cmake --build build-deb --parallel 4
|
||||
cpack --config build-deb/CPackConfig.cmake \
|
||||
@@ -143,12 +165,14 @@ jobs:
|
||||
- name: Build RPM
|
||||
shell: bash
|
||||
run: |
|
||||
nightly_suffix=".nightly.$(git show -s --format=%cd --date=format:%Y%m%d%H%M%S "$GITHUB_SHA").g${GITHUB_SHA:0:8}"
|
||||
docker run --rm \
|
||||
--volume "$GITHUB_WORKSPACE:/workspace" \
|
||||
--workdir /workspace \
|
||||
--env MOCKTAIL_PACKAGE_VERSION_SUFFIX="$nightly_suffix" \
|
||||
fedora:44 bash -Eeuo pipefail -c '
|
||||
dnf install --assumeyes \
|
||||
gcc-c++ cmake git ninja-build pkgconf-pkg-config rpm-build \
|
||||
gcc-c++ cmake git ninja-build pkgconf-pkg-config lld rpm-build \
|
||||
SDL3-devel SDL3_ttf-devel libcurl-devel openssl-devel \
|
||||
nlohmann-json-devel libyaml-devel elfutils-libelf-devel \
|
||||
minizip-ng-compat-devel capstone-devel gtk4-devel libadwaita-devel \
|
||||
@@ -158,6 +182,8 @@ jobs:
|
||||
cmake -S . -B build-rpm -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DMOCKTAIL_PACKAGE_NAME=mocktail-nightly \
|
||||
-DMOCKTAIL_PACKAGE_VERSION_SUFFIX="$MOCKTAIL_PACKAGE_VERSION_SUFFIX" \
|
||||
-DBUILD_TESTING=OFF
|
||||
cmake --build build-rpm --parallel 4
|
||||
cpack --config build-rpm/CPackConfig.cmake \
|
||||
@@ -192,7 +218,7 @@ jobs:
|
||||
--workdir /workspace \
|
||||
archlinux:base-devel bash -Eeuo pipefail -c '
|
||||
pacman -Syu --needed --noconfirm \
|
||||
cmake git ninja pkgconf sdl3 sdl3_ttf curl openssl \
|
||||
cmake git ninja pkgconf lld sdl3 sdl3_ttf curl openssl \
|
||||
nlohmann-json libyaml libelf minizip capstone gtk4 \
|
||||
libadwaita webkitgtk-6.0 libutf8proc fontconfig \
|
||||
libplacebo vulkan-headers vulkan-icd-loader libglvnd zlib
|
||||
@@ -219,7 +245,7 @@ jobs:
|
||||
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
|
||||
needs: [appimage, deb, rpm, arch]
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 15
|
||||
timeout-minutes: 30
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
@@ -235,13 +261,52 @@ jobs:
|
||||
path: release
|
||||
merge-multiple: true
|
||||
|
||||
- name: Prepare continuous packages
|
||||
shell: bash
|
||||
run: |
|
||||
set -Eeuo pipefail
|
||||
mv -- release/*.AppImage release/mocktail-nightly.AppImage
|
||||
mv -- release/*.deb release/mocktail-nightly.deb
|
||||
mv -- release/*.rpm release/mocktail-nightly.rpm
|
||||
mv -- release/*.pkg.tar.zst release/mocktail-nightly.pkg.tar.zst
|
||||
find release -maxdepth 1 -type f -print
|
||||
|
||||
- name: Build package repositories
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
FLATPAK_GPG_PRIVATE_KEY: ${{ secrets.FLATPAK_GPG_PRIVATE_KEY }}
|
||||
FLATPAK_GPG_KEY_ID: ${{ secrets.FLATPAK_GPG_KEY_ID }}
|
||||
run: |
|
||||
set -Eeuo pipefail
|
||||
[[ -n "$FLATPAK_GPG_PRIVATE_KEY" && -n "$FLATPAK_GPG_KEY_ID" ]]
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes --no-install-recommends \
|
||||
apt-utils createrepo-c gnupg rpm
|
||||
install -d stable/deb stable/rpm
|
||||
stable_tag="$(gh api "repos/$GITHUB_REPOSITORY/releases/latest" --jq .tag_name)"
|
||||
gh release download "$stable_tag" --pattern '*.deb' --dir stable/deb
|
||||
gh release download "$stable_tag" --pattern '*.rpm' --dir stable/rpm
|
||||
mapfile -t stable_debs < <(find stable/deb -maxdepth 1 -type f -name '*.deb' -print)
|
||||
mapfile -t stable_rpms < <(find stable/rpm -maxdepth 1 -type f -name '*.rpm' -print)
|
||||
[[ "${#stable_debs[@]}" -eq 1 && "${#stable_rpms[@]}" -eq 1 ]]
|
||||
install -d -m 0700 "$RUNNER_TEMP/mocktail-native-gnupg"
|
||||
printf '%s' "$FLATPAK_GPG_PRIVATE_KEY" | \
|
||||
gpg --batch --homedir "$RUNNER_TEMP/mocktail-native-gnupg" --import
|
||||
gpg --batch --homedir "$RUNNER_TEMP/mocktail-native-gnupg" \
|
||||
--export "$FLATPAK_GPG_KEY_ID" >mocktail-packages.gpg
|
||||
./scripts/assemble_native_repositories.sh \
|
||||
"${stable_debs[0]}" release/mocktail-nightly.deb \
|
||||
"${stable_rpms[0]}" release/mocktail-nightly.rpm \
|
||||
mocktail-packages.gpg "$FLATPAK_GPG_KEY_ID" \
|
||||
"$RUNNER_TEMP/mocktail-native-gnupg" native-repositories
|
||||
|
||||
- name: Update continuous release
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -Eeuo pipefail
|
||||
find release -maxdepth 1 -type f -print
|
||||
git config user.name komaruworld
|
||||
git config user.email rtysus228@gmail.com
|
||||
git tag --force continuous "$GITHUB_SHA"
|
||||
@@ -253,3 +318,20 @@ jobs:
|
||||
--notes "Automated development packages from main."
|
||||
fi
|
||||
gh release upload continuous release/* --clobber
|
||||
while IFS= read -r asset; do
|
||||
case "$asset" in
|
||||
mocktail-nightly.AppImage|mocktail-nightly.deb|mocktail-nightly.rpm|mocktail-nightly.pkg.tar.zst)
|
||||
;;
|
||||
Mocktail-*.AppImage|mocktail_*.deb|mocktail-*.deb|mocktail-*.rpm|mocktail-*.pkg.tar.zst)
|
||||
gh release delete-asset continuous "$asset" --yes
|
||||
;;
|
||||
esac
|
||||
done < <(gh release view continuous --json assets --jq '.assets[].name')
|
||||
|
||||
- name: Upload package repositories
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: Mocktail-native-repositories
|
||||
path: native-repositories
|
||||
if-no-files-found: error
|
||||
retention-days: 14
|
||||
+126
-5
@@ -8,7 +8,7 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
project(Mocktail
|
||||
VERSION 0.1.0
|
||||
VERSION 1.0.3
|
||||
DESCRIPTION "Android x86-64 Roblox compatibility runtime for Linux"
|
||||
LANGUAGES CXX
|
||||
)
|
||||
@@ -16,6 +16,40 @@ project(Mocktail
|
||||
include(GNUInstallDirs)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
set(MOCKTAIL_BUILD_GIT_COMMIT "unknown")
|
||||
set(MOCKTAIL_BUILD_GIT_DIRTY "unknown")
|
||||
find_package(Git QUIET)
|
||||
if(Git_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" rev-parse --short=12 HEAD
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE MOCKTAIL_GIT_REV_PARSE_RESULT
|
||||
OUTPUT_VARIABLE MOCKTAIL_GIT_REV_PARSE_OUTPUT
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
if(MOCKTAIL_GIT_REV_PARSE_RESULT EQUAL 0 AND
|
||||
MOCKTAIL_GIT_REV_PARSE_OUTPUT MATCHES "^[0-9a-fA-F]+$")
|
||||
string(TOLOWER "${MOCKTAIL_GIT_REV_PARSE_OUTPUT}"
|
||||
MOCKTAIL_BUILD_GIT_COMMIT)
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" status --porcelain --untracked-files=normal
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE MOCKTAIL_GIT_STATUS_RESULT
|
||||
OUTPUT_VARIABLE MOCKTAIL_GIT_STATUS_OUTPUT
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
if(MOCKTAIL_GIT_STATUS_RESULT EQUAL 0)
|
||||
if(MOCKTAIL_GIT_STATUS_OUTPUT STREQUAL "")
|
||||
set(MOCKTAIL_BUILD_GIT_DIRTY "false")
|
||||
else()
|
||||
set(MOCKTAIL_BUILD_GIT_DIRTY "true")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(MOCKTAIL_DEFAULT_COMPATIBILITY_MANIFEST
|
||||
"${CMAKE_SOURCE_DIR}/config/roblox_compatibility.json"
|
||||
CACHE FILEPATH
|
||||
@@ -26,6 +60,18 @@ set(MOCKTAIL_DEFAULT_SIGNING_TRUST_MANIFEST
|
||||
CACHE FILEPATH
|
||||
"Fallback signing trust manifest used outside an installed runtime"
|
||||
)
|
||||
set(MOCKTAIL_DISCORD_APPLICATION_ID "1537088975720812655" CACHE STRING
|
||||
"Discord application ID baked into Mocktail Rich Presence releases"
|
||||
)
|
||||
string(LENGTH "${MOCKTAIL_DISCORD_APPLICATION_ID}"
|
||||
MOCKTAIL_DISCORD_APPLICATION_ID_LENGTH)
|
||||
if(NOT MOCKTAIL_DISCORD_APPLICATION_ID STREQUAL "" AND
|
||||
(NOT MOCKTAIL_DISCORD_APPLICATION_ID MATCHES "^[0-9]+$" OR
|
||||
MOCKTAIL_DISCORD_APPLICATION_ID_LENGTH LESS 17 OR
|
||||
MOCKTAIL_DISCORD_APPLICATION_ID_LENGTH GREATER 20))
|
||||
message(FATAL_ERROR
|
||||
"MOCKTAIL_DISCORD_APPLICATION_ID must be empty or a Discord snowflake")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
@@ -221,6 +267,7 @@ target_include_directories(mocktail_legacy_jnivm PUBLIC
|
||||
add_library(mocktail_runtime STATIC
|
||||
src/runtime/command_line.cc
|
||||
src/runtime/crash_report_policy.cc
|
||||
src/runtime/discord_rpc.cc
|
||||
src/runtime/device_profile.cc
|
||||
src/runtime/environment.cc
|
||||
src/runtime/external_launch_broker.cc
|
||||
@@ -246,6 +293,7 @@ add_library(mocktail_runtime STATIC
|
||||
src/runtime/runtime_config_bootstrap.cc
|
||||
src/runtime/runtime_config_file.cc
|
||||
src/runtime/runtime_paths.cc
|
||||
src/runtime/session_log.cc
|
||||
src/runtime/single_instance_lock.cc
|
||||
src/runtime/startup_state_machine.cc
|
||||
src/runtime/supported_launch_policy.cc
|
||||
@@ -256,6 +304,20 @@ target_include_directories(mocktail_runtime PUBLIC include)
|
||||
target_include_directories(mocktail_runtime PUBLIC
|
||||
${MOCKTAIL_JNI_INCLUDE_DIRS}
|
||||
)
|
||||
target_compile_definitions(mocktail_runtime PRIVATE
|
||||
"MOCKTAIL_DISCORD_APPLICATION_ID=\"${MOCKTAIL_DISCORD_APPLICATION_ID}\""
|
||||
)
|
||||
set_property(SOURCE src/runtime/session_log.cc APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS
|
||||
"MOCKTAIL_PROJECT_VERSION=\"${PROJECT_VERSION}\""
|
||||
"MOCKTAIL_BUILD_GIT_COMMIT=\"${MOCKTAIL_BUILD_GIT_COMMIT}\""
|
||||
"MOCKTAIL_BUILD_GIT_DIRTY=\"${MOCKTAIL_BUILD_GIT_DIRTY}\""
|
||||
"MOCKTAIL_BUILD_TYPE=\"$<CONFIG>\""
|
||||
"MOCKTAIL_BUILD_COMPILER_ID=\"${CMAKE_CXX_COMPILER_ID}\""
|
||||
"MOCKTAIL_BUILD_COMPILER_VERSION=\"${CMAKE_CXX_COMPILER_VERSION}\""
|
||||
"MOCKTAIL_BUILD_TARGET_SYSTEM=\"${CMAKE_SYSTEM_NAME}\""
|
||||
"MOCKTAIL_BUILD_TARGET_PROCESSOR=\"${CMAKE_SYSTEM_PROCESSOR}\""
|
||||
)
|
||||
mocktail_apply_compile_options(mocktail_runtime)
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND
|
||||
CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16)
|
||||
@@ -348,9 +410,6 @@ target_link_libraries(mocktail_auth_runtime_composition PUBLIC
|
||||
mocktail_runtime
|
||||
mocktail_services
|
||||
)
|
||||
target_link_libraries(mocktail_auth_runtime_composition PRIVATE
|
||||
Mocktail::CryptoFoundation
|
||||
)
|
||||
mocktail_apply_compile_options(mocktail_auth_runtime_composition)
|
||||
|
||||
add_library(mocktail_linker STATIC
|
||||
@@ -568,6 +627,40 @@ target_link_options(mocktail PRIVATE
|
||||
-Wl,--export-dynamic
|
||||
)
|
||||
|
||||
# Native FreeBSD helper for Linuxulator's unsupported DF socket option.
|
||||
option(MOCKTAIL_BUILD_FREEBSD_SOCKET_HELPER
|
||||
"Build the native FreeBSD Linuxulator socket helper" ON)
|
||||
if(MOCKTAIL_BUILD_FREEBSD_SOCKET_HELPER)
|
||||
find_program(MOCKTAIL_LLD_EXECUTABLE NAMES ld.lld REQUIRED)
|
||||
find_program(MOCKTAIL_ELFEDIT_EXECUTABLE NAMES elfedit REQUIRED)
|
||||
get_filename_component(MOCKTAIL_LLD_DIRECTORY
|
||||
"${MOCKTAIL_LLD_EXECUTABLE}" DIRECTORY)
|
||||
set(MOCKTAIL_FREEBSD_SOCKET_HELPER
|
||||
"${CMAKE_BINARY_DIR}/mocktail_freebsd_socket_helper")
|
||||
add_custom_command(
|
||||
OUTPUT "${MOCKTAIL_FREEBSD_SOCKET_HELPER}"
|
||||
COMMAND "${CMAKE_CXX_COMPILER}"
|
||||
-x assembler-with-cpp
|
||||
-nostdlib
|
||||
-static
|
||||
-no-pie
|
||||
"-B${MOCKTAIL_LLD_DIRECTORY}/"
|
||||
-fuse-ld=lld
|
||||
-Wl,-e,_start,--build-id=none,-z,noexecstack
|
||||
-o "${MOCKTAIL_FREEBSD_SOCKET_HELPER}"
|
||||
"${CMAKE_SOURCE_DIR}/src/compat/freebsd_socket_helper.S"
|
||||
COMMAND "${MOCKTAIL_ELFEDIT_EXECUTABLE}"
|
||||
--output-osabi FreeBSD "${MOCKTAIL_FREEBSD_SOCKET_HELPER}"
|
||||
DEPENDS "${CMAKE_SOURCE_DIR}/src/compat/freebsd_socket_helper.S"
|
||||
COMMENT "Building native FreeBSD Linuxulator socket helper"
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(mocktail_freebsd_socket_helper_build ALL
|
||||
DEPENDS "${MOCKTAIL_FREEBSD_SOCKET_HELPER}"
|
||||
)
|
||||
add_dependencies(mocktail mocktail_freebsd_socket_helper_build)
|
||||
endif()
|
||||
|
||||
set_target_properties(mocktail PROPERTIES
|
||||
BUILD_RPATH "\$ORIGIN"
|
||||
INSTALL_RPATH "\$ORIGIN;\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}/mocktail"
|
||||
@@ -600,6 +693,11 @@ install(TARGETS
|
||||
RUNTIME DESTINATION "${MOCKTAIL_INSTALL_RUNTIME_DIR}"
|
||||
LIBRARY DESTINATION "${MOCKTAIL_INSTALL_RUNTIME_DIR}"
|
||||
)
|
||||
if(MOCKTAIL_BUILD_FREEBSD_SOCKET_HELPER)
|
||||
install(PROGRAMS "${MOCKTAIL_FREEBSD_SOCKET_HELPER}"
|
||||
DESTINATION "${MOCKTAIL_INSTALL_RUNTIME_DIR}"
|
||||
)
|
||||
endif()
|
||||
install(FILES
|
||||
config/roblox_compatibility.json
|
||||
config/roblox_bootstrap_sources.json
|
||||
@@ -655,7 +753,20 @@ install(CODE "
|
||||
endif()
|
||||
")
|
||||
|
||||
set(CPACK_PACKAGE_NAME "mocktail")
|
||||
set(MOCKTAIL_PACKAGE_NAME "mocktail" CACHE STRING
|
||||
"Native package name"
|
||||
)
|
||||
set(MOCKTAIL_PACKAGE_VERSION_SUFFIX "" CACHE STRING
|
||||
"Native package version suffix"
|
||||
)
|
||||
if(NOT MOCKTAIL_PACKAGE_NAME STREQUAL "mocktail" AND
|
||||
NOT MOCKTAIL_PACKAGE_NAME STREQUAL "mocktail-nightly")
|
||||
message(FATAL_ERROR
|
||||
"MOCKTAIL_PACKAGE_NAME must be mocktail or mocktail-nightly")
|
||||
endif()
|
||||
|
||||
set(CPACK_PACKAGE_NAME "${MOCKTAIL_PACKAGE_NAME}")
|
||||
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}${MOCKTAIL_PACKAGE_VERSION_SUFFIX}")
|
||||
set(CPACK_PACKAGE_VENDOR "Mocktail Project")
|
||||
set(CPACK_PACKAGE_CONTACT "komaruworld <rtysus228@gmail.com>")
|
||||
set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/komaruworld/mocktail")
|
||||
@@ -677,6 +788,16 @@ set(CPACK_RPM_FILE_NAME RPM-DEFAULT)
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "Apache-2.0")
|
||||
set(CPACK_RPM_PACKAGE_GROUP "Amusements/Games")
|
||||
set(CPACK_RPM_PACKAGE_AUTOREQPROV ON)
|
||||
|
||||
if(MOCKTAIL_PACKAGE_NAME STREQUAL "mocktail-nightly")
|
||||
set(CPACK_DEBIAN_PACKAGE_CONFLICTS "mocktail")
|
||||
set(CPACK_DEBIAN_PACKAGE_REPLACES "mocktail")
|
||||
set(CPACK_RPM_PACKAGE_CONFLICTS "mocktail")
|
||||
else()
|
||||
set(CPACK_DEBIAN_PACKAGE_CONFLICTS "mocktail-nightly")
|
||||
set(CPACK_DEBIAN_PACKAGE_REPLACES "mocktail-nightly")
|
||||
set(CPACK_RPM_PACKAGE_CONFLICTS "mocktail-nightly")
|
||||
endif()
|
||||
include(CPack)
|
||||
|
||||
add_dependencies(mocktail all_stubs)
|
||||
|
||||
@@ -187,7 +187,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
Copyright 2026 komaruworld
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.DEFAULT_GOAL := all
|
||||
.PHONY: all build release debug test apk install register-url-handler release-runtime portable portable-test standalone appimage flatpak run-flatpak run run-smoke run-unlimited run-game run-input run-resize run-network auto-run run-gles run-angle update-roblox update-auto update-auto-launch install-updater payload-status payload-rollback support-bundle clean submodules help
|
||||
.PHONY: all build release debug test apk install register-url-handler release-runtime portable portable-test standalone appimage flatpak run-flatpak run run-smoke run-unlimited run-game run-input run-resize run-network auto-run run-gles run-angle update-roblox update-auto update-auto-launch payload-status payload-rollback support-bundle clean submodules help
|
||||
|
||||
BUILD_DIR := build
|
||||
BINARY := $(BUILD_DIR)/mocktail
|
||||
@@ -134,16 +134,13 @@ run-angle: ## Run with ANGLE/Vulkan compatibility backend
|
||||
update-roblox: ## Validate and import the current x86_64 Roblox bundle cached by Sober
|
||||
@./scripts/update_roblox_payload.sh
|
||||
|
||||
update-auto: build ## Download latest Roblox, derive its ABI, canary twice and activate safely
|
||||
update-auto: build ## Download latest Roblox, derive its ABI, run two canaries, then activate
|
||||
@./$(BUILD_DIR)/mocktail_updater update
|
||||
|
||||
update-auto-launch: build ## Update Roblox and launch the verified current payload
|
||||
@./$(BUILD_DIR)/mocktail_updater update
|
||||
@./$(BINARY)
|
||||
|
||||
install-updater: ## Install and enable the six-hour systemd user update timer
|
||||
@./scripts/install_user_updater.sh
|
||||
|
||||
payload-status: build ## Show current and previous-good immutable payloads
|
||||
@./$(BUILD_DIR)/mocktail_updater status
|
||||
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
[](https://github.com/komaruworld/mocktail/releases/latest)
|
||||
[](LICENSE)
|
||||
|
||||
Mocktail runs the Android `x86_64` Roblox client on Linux. It provides the
|
||||
Android ABI and JNI pieces the client expects, then uses SDL3 and Vulkan or
|
||||
OpenGL for the Linux side.
|
||||
Mocktail runs the Android `x86_64` Roblox client on Linux, including a Linux
|
||||
userspace hosted by FreeBSD's Linuxulator. It provides the Android ABI and JNI
|
||||
pieces the client expects, then connects them to SDL3 and Vulkan or OpenGL on
|
||||
the Linux side.
|
||||
|
||||
Mocktail is still experimental and may break after a Roblox update. It is not
|
||||
affiliated with Roblox Corporation or VinegarHQ.
|
||||
Mocktail is an independent community project. It is not affiliated with Roblox
|
||||
Corporation or VinegarHQ and does not distribute the Roblox client.
|
||||
|
||||
## How it works
|
||||
|
||||
@@ -24,8 +25,17 @@ an update fails.
|
||||
|
||||
## Install with Flatpak
|
||||
|
||||
Install the stable release from Flathub:
|
||||
|
||||
```bash
|
||||
flatpak install --user https://komaruworld.github.io/mocktail/mocktail.flatpakref
|
||||
flatpak install flathub space.bigrat.mocktail
|
||||
flatpak run space.bigrat.mocktail
|
||||
```
|
||||
|
||||
Nightly builds are produced automatically from the latest `main` branch:
|
||||
|
||||
```bash
|
||||
flatpak install --user https://mocktail.bigrat.space/mocktail.flatpakref
|
||||
flatpak run space.bigrat.mocktail
|
||||
```
|
||||
|
||||
@@ -44,52 +54,82 @@ Use `mocktail` instead of `mocktail-git` to build the pinned release from
|
||||
source, or install the stable prebuilt package with `paru -S mocktail-bin` or
|
||||
`yay -S mocktail-bin`.
|
||||
|
||||
## Screenshots
|
||||
## Install with DNF
|
||||
|
||||
Fedora 44 users can install either the stable `mocktail` package or the
|
||||
`mocktail-nightly` package built from `main`:
|
||||
|
||||
```bash
|
||||
sudo curl -fsSL https://mocktail.bigrat.space/rpm/mocktail.repo \
|
||||
-o /etc/yum.repos.d/mocktail.repo
|
||||
sudo dnf install mocktail
|
||||
# or
|
||||
sudo dnf install mocktail-nightly
|
||||
```
|
||||
|
||||
## Install with APT
|
||||
|
||||
Ubuntu 26.04 users can install either the stable `mocktail` package or the
|
||||
`mocktail-nightly` package built from `main`:
|
||||
|
||||
```bash
|
||||
sudo install -d -m 0755 /etc/apt/keyrings
|
||||
sudo curl -fsSL https://mocktail.bigrat.space/mocktail-packages.gpg \
|
||||
-o /etc/apt/keyrings/mocktail.gpg
|
||||
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/mocktail.gpg] https://mocktail.bigrat.space/apt mocktail main" | \
|
||||
sudo tee /etc/apt/sources.list.d/mocktail.list >/dev/null
|
||||
sudo apt update
|
||||
sudo apt install mocktail
|
||||
# or
|
||||
sudo apt install mocktail-nightly
|
||||
```
|
||||
|
||||
## Direct downloads
|
||||
|
||||
Direct AppImage, DEB, and RPM downloads are available from the
|
||||
[Website](https://mocktail.bigrat.space/) and
|
||||
[GitHub Releases](https://github.com/komaruworld/mocktail/releases).
|
||||
|
||||
<details>
|
||||
<summary>Flatpak build</summary>
|
||||
<summary>Screenshots</summary>
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
</details>
|
||||
|
||||
## Other Linux packages
|
||||
## FFlag overrides
|
||||
|
||||
The latest AppImage, DEB, RPM, and Arch packages are attached to the
|
||||
[continuous release](https://github.com/komaruworld/mocktail/releases/tag/continuous).
|
||||
Put a JSON object in `$XDG_CONFIG_HOME/mocktail/fflags.json` (usually
|
||||
`~/.config/mocktail/fflags.json`). Mocktail applies it on the next launch.
|
||||
|
||||
```bash
|
||||
# AppImage
|
||||
chmod +x Mocktail-x86_64.AppImage
|
||||
./Mocktail-x86_64.AppImage
|
||||
|
||||
# Ubuntu/Debian
|
||||
sudo apt install ./mocktail_*_amd64.deb
|
||||
|
||||
# Fedora
|
||||
sudo dnf install ./mocktail-*.x86_64.rpm
|
||||
|
||||
# Arch Linux
|
||||
sudo pacman -U ./mocktail-*-x86_64.pkg.tar.zst
|
||||
```json
|
||||
{
|
||||
"FFlagExample": "True",
|
||||
"DFIntExample": "120"
|
||||
}
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
Only Linux `x86_64` is supported. Building requires CMake 3.20+, Git,
|
||||
pkg-config, a C++17 compiler, SDL 3.4+, SDL3_ttf, Vulkan, EGL, libplacebo,
|
||||
fontconfig, libcurl, OpenSSL, libelf, libyaml, minizip, Capstone 5, utf8proc,
|
||||
nlohmann/json, GTK4, libadwaita 1.6+, and WebKitGTK 6.0.
|
||||
Linux `x86_64` is supported. Experimental FreeBSD 15.1 Linuxulator support has
|
||||
been tested with an `x86_64` Fedora 44 userspace. On FreeBSD, Mocktail runs
|
||||
inside Linuxulator; it is not a native FreeBSD binary. Building requires CMake
|
||||
3.20+, Git, pkg-config, LLD, binutils, a C++17 compiler, SDL 3.4+, SDL3_ttf,
|
||||
Vulkan, EGL, libplacebo, fontconfig, libcurl, OpenSSL, libelf, libyaml, minizip,
|
||||
Capstone 5, utf8proc, nlohmann/json, GTK4, libadwaita 1.6+, and WebKitGTK 6.0.
|
||||
|
||||
See the [FreeBSD Guide](packaging/freebsd/README.md) for setup and launch instructions.
|
||||
|
||||
<details>
|
||||
<summary>Ubuntu 26.04+</summary>
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install build-essential cmake git ninja-build pkg-config \
|
||||
sudo apt install build-essential cmake git ninja-build pkg-config lld \
|
||||
libsdl3-dev libsdl3-ttf-dev libcurl4-openssl-dev libssl-dev \
|
||||
nlohmann-json3-dev libyaml-dev libelf-dev libminizip-dev \
|
||||
libcapstone-dev libgtk-4-dev libadwaita-1-dev libwebkitgtk-6.0-dev \
|
||||
@@ -102,7 +142,7 @@ sudo apt install build-essential cmake git ninja-build pkg-config \
|
||||
<summary>Arch Linux</summary>
|
||||
|
||||
```bash
|
||||
sudo pacman -S --needed base-devel cmake git ninja pkgconf sdl3 sdl3_ttf \
|
||||
sudo pacman -S --needed base-devel cmake git ninja pkgconf lld sdl3 sdl3_ttf \
|
||||
curl openssl nlohmann-json libyaml libelf minizip capstone gtk4 \
|
||||
libadwaita webkitgtk-6.0 libutf8proc fontconfig libglvnd \
|
||||
libplacebo vulkan-headers vulkan-icd-loader zlib
|
||||
@@ -113,7 +153,7 @@ sudo pacman -S --needed base-devel cmake git ninja pkgconf sdl3 sdl3_ttf \
|
||||
<summary>Fedora 44+</summary>
|
||||
|
||||
```bash
|
||||
sudo dnf install gcc-c++ cmake git ninja-build pkgconf-pkg-config \
|
||||
sudo dnf install gcc-c++ cmake git ninja-build pkgconf-pkg-config lld \
|
||||
SDL3-devel SDL3_ttf-devel libcurl-devel openssl-devel \
|
||||
nlohmann-json-devel libyaml-devel elfutils-libelf-devel minizip-ng-compat-devel \
|
||||
capstone-devel gtk4-devel libadwaita-devel webkitgtk6.0-devel \
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -16,8 +16,10 @@ add_library(mocktail_compat STATIC
|
||||
${MOCKTAIL_ELF_COMPAT_ROOT}/src/compat/bionic_dns_runtime.cc
|
||||
${MOCKTAIL_ELF_COMPAT_ROOT}/src/compat/bionic_host_libc_runtime.cc
|
||||
${MOCKTAIL_ELF_COMPAT_ROOT}/src/compat/bionic_large_file_runtime.cc
|
||||
${MOCKTAIL_ELF_COMPAT_ROOT}/src/compat/bionic_prctl_runtime.cc
|
||||
${MOCKTAIL_ELF_COMPAT_ROOT}/src/compat/bionic_rwlock_runtime.cc
|
||||
${MOCKTAIL_ELF_COMPAT_ROOT}/src/compat/bionic_signal_runtime.cc
|
||||
${MOCKTAIL_ELF_COMPAT_ROOT}/src/compat/bionic_socket_runtime.cc
|
||||
${MOCKTAIL_ELF_COMPAT_ROOT}/src/compat/bionic_semaphore_runtime.cc
|
||||
${MOCKTAIL_ELF_COMPAT_ROOT}/src/compat/bionic_pthread_create_runtime.cc
|
||||
${MOCKTAIL_ELF_COMPAT_ROOT}/src/compat/bionic_pthread_key_runtime.cc
|
||||
@@ -34,6 +36,9 @@ add_library(Mocktail::Compat ALIAS mocktail_compat)
|
||||
target_include_directories(mocktail_compat PUBLIC
|
||||
${MOCKTAIL_ELF_COMPAT_ROOT}/include
|
||||
)
|
||||
target_compile_definitions(mocktail_compat PRIVATE
|
||||
"MOCKTAIL_INSTALL_LIBDIR=\"${CMAKE_INSTALL_LIBDIR}\""
|
||||
)
|
||||
target_link_libraries(mocktail_compat PUBLIC
|
||||
PkgConfig::LIBELF
|
||||
nlohmann_json::nlohmann_json
|
||||
|
||||
@@ -5,7 +5,7 @@ include_guard(GLOBAL)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(UTF8PROC REQUIRED IMPORTED_TARGET libutf8proc)
|
||||
pkg_check_modules(SDL3_TTF REQUIRED IMPORTED_TARGET sdl3-ttf)
|
||||
find_package(SDL3_ttf REQUIRED CONFIG)
|
||||
pkg_check_modules(FONTCONFIG REQUIRED IMPORTED_TARGET fontconfig)
|
||||
|
||||
get_filename_component(MOCKTAIL_INPUT_ROOT "${CMAKE_CURRENT_LIST_DIR}/.."
|
||||
@@ -35,7 +35,7 @@ target_link_libraries(mocktail_input_runtime PUBLIC
|
||||
PkgConfig::UTF8PROC
|
||||
PRIVATE
|
||||
PkgConfig::FONTCONFIG
|
||||
PkgConfig::SDL3_TTF
|
||||
SDL3_ttf::SDL3_ttf
|
||||
)
|
||||
target_compile_features(mocktail_input_runtime PUBLIC cxx_std_17)
|
||||
mocktail_apply_compile_options(mocktail_input_runtime)
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_PLATFORM_SDL_WINDOW_ICON_DATA_H_
|
||||
#define MOCKTAIL_PLATFORM_SDL_WINDOW_ICON_DATA_H_
|
||||
|
||||
|
||||
@@ -64,6 +64,32 @@ audio:
|
||||
# To pin output, copy an exact SDL device name printed during startup.
|
||||
output_device: default
|
||||
|
||||
integrations:
|
||||
discord_rpc:
|
||||
# Boolean (default: false): publish Mocktail activity to Discord Desktop.
|
||||
# This never signs in to Discord and never reads an account token.
|
||||
enabled: false
|
||||
# Boolean (default: true): show the current Roblox experience name.
|
||||
show_place_name: true
|
||||
# Boolean (default: true): show how long the current session has run.
|
||||
show_elapsed_time: true
|
||||
join:
|
||||
# Boolean (default: true): let friends open the current experience. When
|
||||
# Roblox provides a public server ID, the button targets that server.
|
||||
enabled: true
|
||||
# Boolean (default: true): never expose private or reserved joins.
|
||||
public_servers_only: true
|
||||
# button_label: Join Server
|
||||
# English defaults. Uncomment only the lines you want to customize.
|
||||
# text:
|
||||
# browsing: Browsing experiences
|
||||
# joining: Joining an experience
|
||||
# playing: "{place_name}"
|
||||
# state: Playing Roblox
|
||||
# unknown_place: Unknown experience
|
||||
# Advanced: overrides the application bundled by the package maintainer.
|
||||
# application_id: 123456789012345678
|
||||
|
||||
window:
|
||||
# Integer (default: 1280): initial window width in pixels.
|
||||
width: 1280
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
[Unit]
|
||||
Description=Check, canary, and install the latest working Roblox for Mocktail
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
EnvironmentFile=%h/.config/mocktail/updater.env
|
||||
ExecStart=/usr/bin/env ${MOCKTAIL_UPDATE_HELPER} update
|
||||
Nice=10
|
||||
IOSchedulingClass=best-effort
|
||||
IOSchedulingPriority=7
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
@@ -1,12 +0,0 @@
|
||||
[Unit]
|
||||
Description=Periodically check Roblox updates for Mocktail
|
||||
|
||||
[Timer]
|
||||
OnBootSec=5m
|
||||
OnUnitActiveSec=6h
|
||||
RandomizedDelaySec=15m
|
||||
Persistent=true
|
||||
Unit=mocktail-update.service
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_BIONIC_ABI_EXPORTS_H_
|
||||
#define MOCKTAIL_COMPAT_BIONIC_ABI_EXPORTS_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_BIONIC_ATFORK_RUNTIME_H_
|
||||
#define MOCKTAIL_COMPAT_BIONIC_ATFORK_RUNTIME_H_
|
||||
|
||||
@@ -19,16 +5,8 @@ namespace mocktail::compat {
|
||||
|
||||
using BionicAtForkCallback = void (*)(void);
|
||||
|
||||
// Registers Android's __register_atfork callback contract with the host
|
||||
// pthread runtime. Bionic associates registrations with dso_handle and
|
||||
// removes them when that DSO unloads. POSIX pthread_atfork has no matching
|
||||
// unregister operation, so the host bridge accepts dso_handle for ABI
|
||||
// compatibility but cannot use it for cleanup.
|
||||
//
|
||||
// Callback code must remain mapped for every later fork. In practice, a guest
|
||||
// DSO that has registered callbacks must stay loaded until process exit;
|
||||
// unloading is safe only when the process guarantees that it will never fork
|
||||
// again.
|
||||
// POSIX cannot unregister by dso_handle, so registered guest callbacks must
|
||||
// remain mapped for every later fork.
|
||||
int RegisterBionicAtFork(BionicAtForkCallback prepare,
|
||||
BionicAtForkCallback parent,
|
||||
BionicAtForkCallback child, void* dso_handle) noexcept;
|
||||
@@ -37,8 +15,6 @@ int RegisterBionicAtFork(BionicAtForkCallback prepare,
|
||||
|
||||
extern "C" {
|
||||
|
||||
// Exact LP64 Android/Bionic __register_atfork signature. The prefixed host
|
||||
// symbol is exported to the guest as "__register_atfork" by synthetic libc.so.
|
||||
int mocktail_bionic_register_atfork(
|
||||
mocktail::compat::BionicAtForkCallback prepare,
|
||||
mocktail::compat::BionicAtForkCallback parent,
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_BIONIC_DNS_RUNTIME_H_
|
||||
#define MOCKTAIL_COMPAT_BIONIC_DNS_RUNTIME_H_
|
||||
|
||||
|
||||
@@ -1,32 +1,18 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_BIONIC_HOST_LIBC_RUNTIME_H_
|
||||
#define MOCKTAIL_COMPAT_BIONIC_HOST_LIBC_RUNTIME_H_
|
||||
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace mocktail::compat {
|
||||
|
||||
// Android x86-64's malloc.h declares ten size_t fields in this order. This is
|
||||
// not the host's struct mallinfo: glibc's legacy type uses int,
|
||||
// and musl exposes no allocator-telemetry API. On hosts without a compatible
|
||||
// size_t-based telemetry API, BionicMallinfo returns an all-zero "unknown"
|
||||
// snapshot. Callers must not interpret that fallback as proof of zero usage.
|
||||
// Android uses size_t fields here; glibc uses int and musl has no equivalent.
|
||||
// An all-zero fallback means unknown, not zero usage.
|
||||
struct BionicMallinfoSnapshot {
|
||||
size_t arena = 0;
|
||||
size_t ordblks = 0;
|
||||
@@ -44,10 +30,7 @@ struct BionicLocaleState;
|
||||
using BionicLocale = BionicLocaleState*;
|
||||
using BionicThreadDestructor = void (*)(void*);
|
||||
|
||||
// Do not use the host socket structs here. Although glibc happens to match
|
||||
// Android LP64, musl declares cmsg_len and msg_controllen as 32-bit socklen_t.
|
||||
// Bionic x86-64 uses size_t for both, as audited from the vendored
|
||||
// bionic/libc/include/sys/socket.h.
|
||||
// Bionic uses size_t where musl uses 32-bit socklen_t.
|
||||
struct BionicMessageHeader {
|
||||
void* msg_name = nullptr;
|
||||
uint32_t msg_namelen = 0;
|
||||
@@ -64,35 +47,33 @@ struct BionicControlMessageHeader {
|
||||
int cmsg_type = 0;
|
||||
};
|
||||
|
||||
// Implements Android's exported CMSG_NXTHDR helper over the explicit Bionic
|
||||
// x86-64 msghdr/cmsghdr layout above. Malformed or truncated control buffers
|
||||
// fail closed with nullptr.
|
||||
// Malformed or truncated control buffers return nullptr.
|
||||
BionicControlMessageHeader* BionicCmsgNextHeader(
|
||||
BionicMessageHeader* message, BionicControlMessageHeader* current) noexcept;
|
||||
|
||||
// Registers one destructor for the current thread using libstdc++'s Itanium
|
||||
// C++ ABI implementation. That implementation is present on both supported
|
||||
// glibc and musl toolchains and preserves destructor execution at thread exit.
|
||||
// Uses libstdc++'s Itanium ABI on both supported libc implementations.
|
||||
int BionicCxaThreadAtExit(BionicThreadDestructor destructor, void* argument,
|
||||
void* dso_handle) noexcept;
|
||||
|
||||
// Fills the complete buffer from the Linux kernel RNG. The implementation
|
||||
// falls back to /dev/urandom only when getrandom is unavailable or blocked and
|
||||
// aborts rather than returning predictable or partially initialized bytes.
|
||||
// Falls back to /dev/urandom; never returns partial or predictable bytes.
|
||||
void BionicArc4RandomBuffer(void* buffer, size_t size) noexcept;
|
||||
|
||||
BionicMallinfoSnapshot BionicMallinfo() noexcept;
|
||||
bool BionicMallinfoHasHostTelemetry() noexcept;
|
||||
|
||||
// Formats one Linux errno value using Bionic's POSIX strerror_r contract.
|
||||
// Unlike glibc's GNU variant, success is reported as zero; truncation returns
|
||||
// -1 and sets errno to ERANGE while preserving the caller's errno on success.
|
||||
void NormalizeBionicSysInfo(struct sysinfo* info) noexcept;
|
||||
int BionicSysInfo(struct sysinfo* info) noexcept;
|
||||
bool NormalizeLinuxulatorUnameVersion(struct utsname* name,
|
||||
const char* linux_version) noexcept;
|
||||
int BionicUname(struct utsname* name) noexcept;
|
||||
uid_t NormalizeBionicApplicationUid(uid_t host_uid) noexcept;
|
||||
uid_t BionicGetUid() noexcept;
|
||||
uid_t BionicGetEffectiveUid() noexcept;
|
||||
|
||||
// POSIX strerror_r contract: zero on success, -1/ERANGE on truncation.
|
||||
int BionicStrError(int error_number, char* buffer, size_t buffer_size) noexcept;
|
||||
|
||||
// Bionic supports only C and C.UTF-8, whose integer parsing is identical. A
|
||||
// host C locale is installed only for the duration of each call, so ambient
|
||||
// process locale cannot change guest parsing and a Bionic locale pointer is
|
||||
// never mistaken for an incompatible host locale_t.
|
||||
// Parses under host C locale without passing an incompatible Bionic locale_t.
|
||||
long long BionicStrToLongLongLocale(const char* text, char** end, int base,
|
||||
BionicLocale locale) noexcept;
|
||||
unsigned long long BionicStrToUnsignedLongLongLocale(
|
||||
@@ -110,6 +91,10 @@ int mocktail_bionic_cxa_thread_atexit_impl(
|
||||
void* dso_handle);
|
||||
void mocktail_bionic_arc4random_buf(void* buffer, size_t size);
|
||||
mocktail::compat::BionicMallinfoSnapshot mocktail_bionic_mallinfo();
|
||||
int mocktail_bionic_sysinfo(struct sysinfo* info);
|
||||
int mocktail_bionic_uname(struct utsname* name);
|
||||
uid_t mocktail_bionic_getuid();
|
||||
uid_t mocktail_bionic_geteuid();
|
||||
int mocktail_bionic_strerror_r(int error_number, char* buffer,
|
||||
size_t buffer_size);
|
||||
long long mocktail_bionic_strtoll_l(const char* text, char** end, int base,
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_BIONIC_LARGE_FILE_RUNTIME_H_
|
||||
#define MOCKTAIL_COMPAT_BIONIC_LARGE_FILE_RUNTIME_H_
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef MOCKTAIL_COMPAT_BIONIC_PRCTL_RUNTIME_H_
|
||||
#define MOCKTAIL_COMPAT_BIONIC_PRCTL_RUNTIME_H_
|
||||
|
||||
extern "C" {
|
||||
|
||||
int mocktail_bionic_prctl(int option, unsigned long argument2,
|
||||
unsigned long argument3, unsigned long argument4,
|
||||
unsigned long argument5);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // MOCKTAIL_COMPAT_BIONIC_PRCTL_RUNTIME_H_
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_BIONIC_PTHREAD_CREATE_RUNTIME_H_
|
||||
#define MOCKTAIL_COMPAT_BIONIC_PTHREAD_CREATE_RUNTIME_H_
|
||||
|
||||
@@ -23,30 +9,21 @@ namespace mocktail::compat {
|
||||
|
||||
using NativeThreadInitializer = void (*)();
|
||||
|
||||
// Pinned Bionic LP64 pthread_internal.h keeps total per-thread reservation
|
||||
// near 1 MiB by subtracting its 32 KiB alternate signal stack from the normal
|
||||
// thread stack. Host defaults are not ABI substitutes: musl's default is only
|
||||
// 128 KiB on the supported Void runtime.
|
||||
// Bionic reserves 32 KiB of its 1 MiB thread allocation for the signal stack.
|
||||
inline constexpr size_t kBionicLp64DefaultThreadStackSize =
|
||||
(1U * 1024U * 1024U) - (32U * 1024U);
|
||||
static_assert(kBionicLp64DefaultThreadStackSize == 1015808U);
|
||||
|
||||
// Used only after a Bionic-sized stack is rejected by the host at thread
|
||||
// creation time. The retry takes the largest of this floor, the requested
|
||||
// guest size, and the host default. That retains enough stack on musl without
|
||||
// shrinking glibc's default.
|
||||
// Retry floor when the host rejects the Bionic-sized stack.
|
||||
inline constexpr size_t kBionicLp64FallbackThreadStackSize = 2U * 1024U * 1024U;
|
||||
|
||||
// Installs the payload-owned per-thread initializer used by subsequently
|
||||
// created guest threads. Passing nullptr restores ordinary host behavior.
|
||||
// nullptr restores host behavior.
|
||||
void ConfigureBionicPthreadThreadInitializer(
|
||||
NativeThreadInitializer initializer) noexcept;
|
||||
|
||||
} // namespace mocktail::compat
|
||||
|
||||
// Creates a host thread after rebuilding the supported POSIX attributes.
|
||||
// Rebuilding avoids passing ABI-private pthread_attr_t state from the Android
|
||||
// payload directly into glibc.
|
||||
// Rebuilds attributes instead of passing Android pthread_attr_t to glibc.
|
||||
extern "C" int mocktail_bionic_pthread_create(pthread_t* thread,
|
||||
const pthread_attr_t* attr,
|
||||
void* (*start_routine)(void*),
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_BIONIC_PTHREAD_KEY_RUNTIME_H_
|
||||
#define MOCKTAIL_COMPAT_BIONIC_PTHREAD_KEY_RUNTIME_H_
|
||||
|
||||
@@ -31,9 +17,8 @@ constexpr uint32_t kBionicPthreadKeyValidFlag = uint32_t{1} << 31;
|
||||
|
||||
using BionicPthreadKeyDestructor = void (*)(void*);
|
||||
|
||||
// implementation of Bionic's pthread_key_* ABI. It owns only guest
|
||||
// keys registered through the synthetic Android libc.so, while ordinary host
|
||||
// code continues to use glibc pthread keys.
|
||||
// Implements Bionic's pthread_key_* ABI for keys registered through the
|
||||
// synthetic libc.so. Host code continues to use glibc pthread keys.
|
||||
class BionicPthreadKeyRuntime {
|
||||
public:
|
||||
static BionicPthreadKeyRuntime& Instance() noexcept;
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_BIONIC_RWLOCK_RUNTIME_H_
|
||||
#define MOCKTAIL_COMPAT_BIONIC_RWLOCK_RUNTIME_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_BIONIC_SEMAPHORE_RUNTIME_H_
|
||||
#define MOCKTAIL_COMPAT_BIONIC_SEMAPHORE_RUNTIME_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_BIONIC_SIGNAL_RUNTIME_H_
|
||||
#define MOCKTAIL_COMPAT_BIONIC_SIGNAL_RUNTIME_H_
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef MOCKTAIL_COMPAT_BIONIC_SOCKET_RUNTIME_H_
|
||||
#define MOCKTAIL_COMPAT_BIONIC_SOCKET_RUNTIME_H_
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
int mocktail_bionic_setsockopt(int socket, int level, int option_name,
|
||||
const void *option_value,
|
||||
socklen_t option_length);
|
||||
|
||||
ssize_t mocktail_bionic_sendmsg(int socket, const struct msghdr *message,
|
||||
int flags);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // MOCKTAIL_COMPAT_BIONIC_SOCKET_RUNTIME_H_
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_BIONIC_STDIO_RUNTIME_H_
|
||||
#define MOCKTAIL_COMPAT_BIONIC_STDIO_RUNTIME_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_BIONIC_SYSCONF_H_
|
||||
#define MOCKTAIL_COMPAT_BIONIC_SYSCONF_H_
|
||||
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_BUILD_PROFILE_H_
|
||||
#define MOCKTAIL_COMPAT_BUILD_PROFILE_H_
|
||||
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_ELF_BUILD_ID_H_
|
||||
#define MOCKTAIL_COMPAT_ELF_BUILD_ID_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_HOST_ABI_EXPERIMENT_H_
|
||||
#define MOCKTAIL_COMPAT_HOST_ABI_EXPERIMENT_H_
|
||||
|
||||
@@ -62,7 +48,7 @@ enum class NativePreJniBootstrapStatus {
|
||||
kFailed,
|
||||
};
|
||||
|
||||
// Installs one exact-Build-ID experiment before libroblox constructors run.
|
||||
// Installs one exact-Build-ID profile before libroblox constructors run.
|
||||
// The caller owns policy: this function never enables itself from environment
|
||||
// variables and must only receive a profile selected from the loaded ELF ID.
|
||||
HostAbiExperimentResult
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_HOST_ABI_PROFILE_H_
|
||||
#define MOCKTAIL_COMPAT_HOST_ABI_PROFILE_H_
|
||||
|
||||
@@ -81,7 +67,7 @@ struct NativeAllocatorProfile {
|
||||
inline constexpr size_t kMaxHostBridgeEntries = 8;
|
||||
inline constexpr size_t kMaxConstructorRunRanges = 26;
|
||||
|
||||
// Build-ID-scoped native ABI knowledge for supported and experimental payload
|
||||
// Build-ID-scoped native ABI knowledge for supported and candidate payload
|
||||
// profiles. Keeping these addresses outside the legacy startup graph makes the
|
||||
// version boundary reviewable and independently testable.
|
||||
struct HostAbiProfile {
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_HOST_ABI_PROFILE_LOADER_H_
|
||||
#define MOCKTAIL_COMPAT_HOST_ABI_PROFILE_LOADER_H_
|
||||
|
||||
@@ -28,11 +14,8 @@ struct FileSha256Result {
|
||||
explicit operator bool() const noexcept { return error.empty(); }
|
||||
};
|
||||
|
||||
// Computes a lowercase SHA-256 digest without invoking a shell or an external
|
||||
// utility. The external ABI approval receipt binds exact profile,
|
||||
// compatibility-manifest, and payload bytes through this implementation; the
|
||||
// runtime itself is bound by its stable GNU Build ID because installation may
|
||||
// rewrite RPATH bytes.
|
||||
// Approval receipts bind the profile, manifest, and payload to this digest.
|
||||
// Runtime identity uses its Build ID because installation may rewrite RPATH.
|
||||
FileSha256Result ComputeFileSha256(const std::string& path);
|
||||
|
||||
struct ExternalHostAbiProfileRequest {
|
||||
@@ -55,27 +38,19 @@ struct ExternalHostAbiProfileResult {
|
||||
explicit operator bool() const noexcept { return error.empty(); }
|
||||
};
|
||||
|
||||
// Loads one exact, payload-bound ABI profile into the process registry. A
|
||||
// candidate is accepted only by an explicitly authorized canary process. A
|
||||
// normal launch instead requires a separate approval receipt produced after
|
||||
// repeated Tier C readiness. Built-in profiles are immutable and always win.
|
||||
// Candidates require canary authorization; normal launches require an
|
||||
// approval receipt. Built-in profiles always win.
|
||||
ExternalHostAbiProfileResult LoadExternalHostAbiProfile(
|
||||
const ExternalHostAbiProfileRequest& request);
|
||||
|
||||
// Environment integration used by the pre-native compatibility gate. An
|
||||
// unset MOCKTAIL_HOST_ABI_PROFILE_FILE is a successful no-op. If it is set,
|
||||
// candidate authorization requires MOCKTAIL_HOST_ABI_CANARY=1,
|
||||
// MOCKTAIL_ALLOW_CANDIDATE_HOST_ABI=1, and the explicit research command-line
|
||||
// marker. Approved profiles require MOCKTAIL_HOST_ABI_APPROVAL_RECEIPT and
|
||||
// neither canary environment marker.
|
||||
// An unset profile is a no-op. Candidates require both canary flags and the
|
||||
// research CLI marker; approved profiles require a receipt and no canary flag.
|
||||
ExternalHostAbiProfileResult InitializeHostAbiProfileFromEnvironment(
|
||||
const std::string& payload_path,
|
||||
const std::string& compatibility_manifest_path,
|
||||
const std::string& expected_build_id,
|
||||
bool explicit_unverified_authorization);
|
||||
|
||||
// Registry lookup used by FindHostAbiProfile after its immutable built-in
|
||||
// table. Callers should use FindHostAbiProfile rather than this function.
|
||||
const HostAbiProfile* FindLoadedExternalHostAbiProfile(
|
||||
std::string_view build_id) noexcept;
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_HOST_ALLOCATOR_BRIDGE_H_
|
||||
#define MOCKTAIL_COMPAT_HOST_ALLOCATOR_BRIDGE_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_HTTP_CLIENT_SPIN_GUARD_H_
|
||||
#define MOCKTAIL_COMPAT_HTTP_CLIENT_SPIN_GUARD_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_COMPAT_PAYLOAD_COMPATIBILITY_H_
|
||||
#define MOCKTAIL_COMPAT_PAYLOAD_COMPATIBILITY_H_
|
||||
|
||||
|
||||
+18
-115
@@ -1,33 +1,5 @@
|
||||
// Copyright 2026 Sober Test Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// jnivm/jnivm.h — Pseudo Java Native Interface Virtual Machine.
|
||||
//
|
||||
// Provides a lightweight C++ implementation of a JVM stub for use with
|
||||
// Android-native shared libraries (e.g., libroblox.so) running on Linux.
|
||||
// No real Java bytecode is executed; instead, all JNI calls are intercepted
|
||||
// and dispatched to registered C++ callbacks.
|
||||
//
|
||||
// Usage:
|
||||
// auto vm = std::make_shared<jnivm::VM>();
|
||||
// auto cls = vm->RegisterClass("android/content/Context");
|
||||
// cls->RegisterMethod("getSystemService",
|
||||
// "(Ljava/lang/String;)Ljava/lang/Object;",
|
||||
// [](JNIEnv*, jobject, ...) { return nullptr; });
|
||||
|
||||
#ifndef SOBER_TEST_JNIVM_JNIVM_H_
|
||||
#define SOBER_TEST_JNIVM_JNIVM_H_
|
||||
#ifndef MOCKTAIL_JNIVM_JNIVM_H_
|
||||
#define MOCKTAIL_JNIVM_JNIVM_H_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
@@ -42,29 +14,20 @@
|
||||
|
||||
namespace jnivm {
|
||||
|
||||
// Forward declarations
|
||||
|
||||
class VM;
|
||||
class Class;
|
||||
|
||||
// Object — base type for all pseudo-Java objects managed by the pseudo-JVM.
|
||||
// Analogous to java.lang.Object in the real JVM.
|
||||
|
||||
class Object {
|
||||
public:
|
||||
explicit Object(std::shared_ptr<Class> klass) : klass_(std::move(klass)) {}
|
||||
virtual ~Object() = default;
|
||||
|
||||
// Returns the pseudo-class descriptor of this object.
|
||||
std::shared_ptr<Class> GetClass() const { return klass_; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<Class> klass_;
|
||||
};
|
||||
|
||||
// MethodCallback — signature for registered JNI method stubs.
|
||||
// The callback receives the raw JNIEnv pointer and the receiver jobject.
|
||||
|
||||
using MethodCallback = std::function<void(JNIEnv *, jobject)>;
|
||||
|
||||
// Resolved Roblox account identity supplied by the host runtime. This
|
||||
@@ -75,8 +38,6 @@ struct RobloxAuthIdentity {
|
||||
std::string display_name;
|
||||
};
|
||||
|
||||
// Host device capabilities exposed through the pseudo Android framework.
|
||||
// The guest ABI remains Android, while the default profile // describes a Linux desktop with physical mouse and keyboard input.
|
||||
struct PlatformIdentity {
|
||||
bool touch_enabled = false;
|
||||
bool mouse_enabled = true;
|
||||
@@ -99,23 +60,16 @@ struct RobloxCredentialView {
|
||||
|
||||
using RobloxCredentialProvider = RobloxCredentialView (*)(const void *context);
|
||||
|
||||
// Creates a Configuration object consistent with the VM's immutable platform
|
||||
// identity snapshot. This is the replacement for legacy construction of
|
||||
// contradictory Android keyboard/touch fields.
|
||||
jobject CreateAndroidConfiguration(JNIEnv *env);
|
||||
|
||||
// Narrow write-only boundary for credentials produced by Roblox after the
|
||||
// native runtime has started. A successfully persisted value supersedes the
|
||||
// bound provider for the remainder of the current VM lifetime so native sign-in
|
||||
// can become authoritative without reopening an untrusted credential source.
|
||||
// A stored credential replaces the bound provider for the rest of this VM's
|
||||
// lifetime.
|
||||
struct RobloxCredentialSinkCallbacks {
|
||||
bool (*store)(void *context, const char *data, std::size_t size) = nullptr;
|
||||
};
|
||||
|
||||
// Narrow host callback boundary for org/fmod/AudioDevice. The pseudo-JVM owns
|
||||
// only an opaque shared context and never depends on the SDL audio runtime.
|
||||
// Each Java receiver is passed as a stable identity so the host can keep
|
||||
// independent device lifecycles without retaining a JNI local reference.
|
||||
// The VM keeps the host context opaque. Receiver identities let the backend
|
||||
// track devices without retaining JNI local references.
|
||||
struct FmodAudioDeviceCallbacks {
|
||||
bool (*init)(void *context, const void *identity, int channels,
|
||||
int sample_rate_hz, int block_size_frames,
|
||||
@@ -126,17 +80,12 @@ struct FmodAudioDeviceCallbacks {
|
||||
void (*shutdown)(void *context) = nullptr;
|
||||
};
|
||||
|
||||
// Narrow host callback boundary for the activity.setWindowFlags(II)V contract.
|
||||
// Production LuaApp retains its activity through the android.app.Activity
|
||||
// interface, while GameActivity startup uses the concrete subclass. Guest JNI
|
||||
// threads only publish Android flags; the platform callback must marshal any
|
||||
// SDL work onto the SDL main thread.
|
||||
// Guest JNI threads only publish Android window flags. The host callback must
|
||||
// marshal SDL work onto the main thread.
|
||||
struct AndroidWindowCallbacks {
|
||||
bool (*set_flags)(void *context, int flags, int mask) = nullptr;
|
||||
};
|
||||
|
||||
// Immutable snapshot of the Android NativeTextBoxInfo payload supplied by
|
||||
// Roblox when a native text field receives focus.
|
||||
struct RobloxTextBoxInfo {
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
@@ -161,8 +110,7 @@ struct RobloxTextInputShowRequest {
|
||||
RobloxTextBoxInfo info;
|
||||
};
|
||||
|
||||
// Narrow callback boundary for the Roblox native text-input callbacks. The
|
||||
// pseudo-JVM snapshots all JNI-owned arguments before entering this boundary.
|
||||
// JNI-owned arguments are copied before the host callback runs.
|
||||
struct RobloxTextInputCallbacks {
|
||||
void (*show)(void *context,
|
||||
const RobloxTextInputShowRequest &request) = nullptr;
|
||||
@@ -172,9 +120,8 @@ struct RobloxTextInputCallbacks {
|
||||
void (*shutdown)(void *context) = nullptr;
|
||||
};
|
||||
|
||||
// Narrow boundary for a native MessageBus RawCallback object. The VM
|
||||
// retains context while a callback is in flight and dispatches only the exact
|
||||
// run(Ljava/lang/String;)V method on the exact created receiver.
|
||||
// Dispatch accepts run(String) only on a receiver created by this VM. The
|
||||
// context stays alive while the callback runs.
|
||||
struct MessageBusRawCallbacks {
|
||||
void (*run)(void *context, JNIEnv *env, jstring message) = nullptr;
|
||||
};
|
||||
@@ -183,18 +130,14 @@ struct MessageBusRequestHandlerCallbacks {
|
||||
std::string (*run)(void *context, JNIEnv *env, jstring message) = nullptr;
|
||||
};
|
||||
|
||||
// Narrow boundary for the current APK's legacy BrowserService transport.
|
||||
// Dispatch accepts only Callback.onItemSet(Ljava/lang/String;)V on the exact
|
||||
// pseudo receiver created by CreateMemStorageCallback.
|
||||
// Dispatch accepts Callback.onItemSet(String) only on a receiver created by
|
||||
// this VM. The context stays alive while the callback runs.
|
||||
struct MemStorageCallbackCallbacks {
|
||||
void (*on_item_set)(void *context, JNIEnv *env, jstring value) = nullptr;
|
||||
};
|
||||
|
||||
// Narrow boundary for the exact APK callbacks that update host web
|
||||
// state: NativeGLJavaInterface notifications, web activities, cookie sync,
|
||||
// and JNICookieProtocol.OnSetCookieHandler. The VM retains the shared callback
|
||||
// context while a callback is in flight; consumers must copy JNI strings
|
||||
// before returning.
|
||||
// Web callbacks share a retained context while in flight. Consumers must copy
|
||||
// JNI strings before returning.
|
||||
struct RobloxDataModelNotificationCallbacks {
|
||||
void (*on_notification)(void *context, JNIEnv *env, jstring type,
|
||||
jstring data) = nullptr;
|
||||
@@ -209,37 +152,22 @@ struct RobloxDataModelNotificationCallbacks {
|
||||
jstring url) = nullptr;
|
||||
};
|
||||
|
||||
// Narrow boundary for the exact NativeHelper lifecycle notification
|
||||
// emitted when Roblox returns from an experience to LuaApp.
|
||||
struct RobloxExperienceLifecycleCallbacks {
|
||||
void (*on_lua_app_did_return)(void *context) = nullptr;
|
||||
};
|
||||
|
||||
// Class — represents a pseudo Java class registered in the pseudo-JVM.
|
||||
// Stores the class name (JNI descriptor format) and a map of method stubs.
|
||||
|
||||
class Class {
|
||||
public:
|
||||
explicit Class(std::string name) : name_(std::move(name)) {}
|
||||
|
||||
// Returns the JNI-style class descriptor, e.g. "android/content/Context".
|
||||
const std::string &GetName() const { return name_; }
|
||||
|
||||
// Registers a JNI method stub.
|
||||
//
|
||||
// Args:
|
||||
// method_name: Simple method name (e.g. "getSystemService").
|
||||
// signature: JNI type descriptor (e.g. "(Ljava/lang/String;)V").
|
||||
// callback: C++ lambda invoked when the method is called via JNI.
|
||||
void RegisterMethod(const std::string &method_name,
|
||||
const std::string &signature, MethodCallback callback);
|
||||
|
||||
// Looks up a method stub by name and signature.
|
||||
// Returns nullptr if not found.
|
||||
const MethodCallback *FindMethod(const std::string &method_name,
|
||||
const std::string &signature) const;
|
||||
|
||||
// Returns all registered methods (name → callback).
|
||||
const std::unordered_map<std::string, MethodCallback> &GetMethods() const {
|
||||
return methods_;
|
||||
}
|
||||
@@ -247,57 +175,37 @@ public:
|
||||
private:
|
||||
std::string name_;
|
||||
|
||||
// Key format: "methodName:descriptor"
|
||||
std::unordered_map<std::string, MethodCallback> methods_;
|
||||
};
|
||||
|
||||
// VM — the top-level pseudo Java Virtual Machine.
|
||||
//
|
||||
// Owns a registry of pseudo-classes and exposes a JavaVM* compatible
|
||||
// pointer for passing to JNI_OnLoad in the loaded shared library.
|
||||
|
||||
class VM {
|
||||
public:
|
||||
VM();
|
||||
~VM();
|
||||
|
||||
// Disallow copy and assign.
|
||||
VM(const VM &) = delete;
|
||||
VM &operator=(const VM &) = delete;
|
||||
|
||||
// Registers a new pseudo-class by its JNI descriptor.
|
||||
// Repeated registration returns the existing instance.
|
||||
//
|
||||
// Args:
|
||||
// class_name: JNI-style descriptor, e.g.
|
||||
// "com/roblox/client/RobloxActivity".
|
||||
//
|
||||
// Returns:
|
||||
// Shared pointer to the registered (or pre-existing) Class object.
|
||||
// Repeated registration returns the existing class.
|
||||
std::shared_ptr<Class> RegisterClass(const std::string &class_name);
|
||||
|
||||
// Finds a previously registered class.
|
||||
// Returns nullptr if the class has not been registered.
|
||||
std::shared_ptr<Class> FindClass(const std::string &class_name) const;
|
||||
|
||||
// Returns the raw JavaVM pointer compatible with JNI_OnLoad signature.
|
||||
JavaVM *GetJavaVM() { return java_vm_; }
|
||||
|
||||
// Resolves the process pseudo-VM that owns an exact JavaVM pointer. Returns
|
||||
// null for foreign VMs and after the owner is destroyed.
|
||||
static VM *FromJavaVM(JavaVM *java_vm);
|
||||
|
||||
// Returns the attached JNIEnv pointer for the current host thread.
|
||||
JNIEnv *GetJNIEnv();
|
||||
|
||||
// Returns the number of registered classes.
|
||||
std::size_t GetClassCount() const { return class_registry_.size(); }
|
||||
|
||||
// Replaces the resolved account identity with an independent copy. Invalid
|
||||
// (non-positive) identities are normalized to the unresolved state.
|
||||
void SetRobloxAuthIdentity(const RobloxAuthIdentity &identity);
|
||||
|
||||
// Returns the VM to its unresolved account state.
|
||||
void ClearRobloxAuthIdentity();
|
||||
|
||||
// Returns an immutable-by-value snapshot safe for use by JNI callbacks on
|
||||
@@ -405,12 +313,10 @@ public:
|
||||
void ClearRobloxExperienceLifecycleCallbacks();
|
||||
bool DispatchRobloxExperienceLuaAppDidReturn();
|
||||
|
||||
// Restores env->functions to &native_interface_ in case libroblox replaced
|
||||
// it.
|
||||
// Restores the pseudo-JNI table after guest code replaces env->functions.
|
||||
void RestoreFunctions();
|
||||
|
||||
private:
|
||||
// Internal JNI function tables populated with stub implementations.
|
||||
JNIInvokeInterface_ invoke_interface_ = {};
|
||||
JavaVM java_vm_storage_ = {};
|
||||
JavaVM *java_vm_ = nullptr;
|
||||
@@ -419,7 +325,6 @@ private:
|
||||
JNIEnv jni_env_storage_ = {};
|
||||
JNIEnv *jni_env_ = nullptr;
|
||||
|
||||
// Registry of pseudo-classes indexed by their JNI descriptor.
|
||||
std::unordered_map<std::string, std::shared_ptr<Class>> class_registry_;
|
||||
|
||||
mutable std::mutex roblox_auth_identity_mutex_;
|
||||
@@ -498,11 +403,9 @@ private:
|
||||
std::shared_ptr<RobloxExperienceLifecycleBinding>
|
||||
roblox_experience_lifecycle_binding_;
|
||||
|
||||
// Initialises the JNIInvokeInterface_ and JNINativeInterface_ function tables
|
||||
// with stub implementations that forward calls to this VM instance.
|
||||
void InitJNIFunctionTables();
|
||||
};
|
||||
|
||||
} // namespace jnivm
|
||||
|
||||
#endif // SOBER_TEST_JNIVM_JNIVM_H_
|
||||
#endif // MOCKTAIL_JNIVM_JNIVM_H_
|
||||
@@ -1,11 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
#ifndef MOCKTAIL_LEGACY_LEGACY_RUNTIME_H_
|
||||
#define MOCKTAIL_LEGACY_LEGACY_RUNTIME_H_
|
||||
|
||||
@@ -33,6 +25,8 @@ class RuntimeDependencies final {
|
||||
: jni_vm_(std::move(composition.jni_vm)),
|
||||
account_identity_(std::move(composition.account_identity)),
|
||||
roblox_credential_(std::move(composition.credential)),
|
||||
clear_persisted_web_view_cookie_(
|
||||
composition.rejected_credential_retired),
|
||||
shutdown_before_platform_(shutdown_before_platform) {}
|
||||
~RuntimeDependencies() {
|
||||
if (jni_vm_ != nullptr && shutdown_before_platform_ != nullptr) {
|
||||
@@ -46,6 +40,8 @@ class RuntimeDependencies final {
|
||||
: jni_vm_(std::move(other.jni_vm_)),
|
||||
account_identity_(std::move(other.account_identity_)),
|
||||
roblox_credential_(std::move(other.roblox_credential_)),
|
||||
clear_persisted_web_view_cookie_(std::exchange(
|
||||
other.clear_persisted_web_view_cookie_, false)),
|
||||
shutdown_before_platform_(
|
||||
std::exchange(other.shutdown_before_platform_, nullptr)) {}
|
||||
RuntimeDependencies& operator=(RuntimeDependencies&& other) noexcept {
|
||||
@@ -58,6 +54,8 @@ class RuntimeDependencies final {
|
||||
jni_vm_ = std::move(other.jni_vm_);
|
||||
account_identity_ = std::move(other.account_identity_);
|
||||
roblox_credential_ = std::move(other.roblox_credential_);
|
||||
clear_persisted_web_view_cookie_ =
|
||||
std::exchange(other.clear_persisted_web_view_cookie_, false);
|
||||
shutdown_before_platform_ =
|
||||
std::exchange(other.shutdown_before_platform_, nullptr);
|
||||
return *this;
|
||||
@@ -70,6 +68,9 @@ class RuntimeDependencies final {
|
||||
const runtime::SecureRobloxCredential& roblox_credential() const {
|
||||
return roblox_credential_;
|
||||
}
|
||||
bool clear_persisted_web_view_cookie() const {
|
||||
return clear_persisted_web_view_cookie_;
|
||||
}
|
||||
|
||||
// Transitional teardown boundary. Runtime-owned subsystems release
|
||||
// SDL resources here after guest workers stop and before window shutdown.
|
||||
@@ -83,10 +84,11 @@ class RuntimeDependencies final {
|
||||
std::shared_ptr<jnivm::VM> jni_vm_;
|
||||
jnivm::RobloxAuthIdentity account_identity_;
|
||||
runtime::SecureRobloxCredential roblox_credential_;
|
||||
bool clear_persisted_web_view_cookie_ = false;
|
||||
ShutdownBeforePlatformCallback shutdown_before_platform_ = nullptr;
|
||||
};
|
||||
|
||||
// Transitional reverse-engineering runtime. New subsystems must expose // interfaces and be composed outside this implementation.
|
||||
// Transitional runtime kept for the reverse-engineered startup path.
|
||||
int Run(const runtime::CommandLineOptions& options,
|
||||
RuntimeDependencies dependencies);
|
||||
|
||||
|
||||
@@ -1,30 +1,5 @@
|
||||
// Copyright 2026 Sober Test Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// libc_shim/libc_shim.h — Bionic libc → Glibc call translation layer.
|
||||
//
|
||||
// Intercepts calls made by Bionic-compiled code (libroblox.so) to
|
||||
// Bionic-specific libc functions and forwards them to their Glibc equivalents
|
||||
// on the host Linux system.
|
||||
//
|
||||
// Key responsibilities:
|
||||
// - pthread_mutex_t size/layout differences between Bionic and Glibc.
|
||||
// - Virtual filesystem path mapping (APK sandbox → Flatpak paths).
|
||||
// - Bionic-only syscall wrappers missing in Glibc.
|
||||
|
||||
#ifndef SOBER_TEST_LIBC_SHIM_LIBC_SHIM_H_
|
||||
#define SOBER_TEST_LIBC_SHIM_LIBC_SHIM_H_
|
||||
#ifndef MOCKTAIL_LIBC_SHIM_LIBC_SHIM_H_
|
||||
#define MOCKTAIL_LIBC_SHIM_LIBC_SHIM_H_
|
||||
|
||||
#include <cstdio>
|
||||
#include <dirent.h>
|
||||
@@ -57,10 +32,8 @@ struct HostCaBundleResolution {
|
||||
// boundary as the caller that will later free them.
|
||||
void ConfigureGuestAllocator(GuestAllocator allocator) noexcept;
|
||||
|
||||
// Installs all shim hooks. Must be called before the target .so is loaded.
|
||||
//
|
||||
// After this call, dlopen(3) symbol resolution for known Bionic symbols will
|
||||
// be intercepted and redirected to the shim implementations.
|
||||
// Must run before loading the target library so its Bionic imports resolve to
|
||||
// these shims.
|
||||
void Install();
|
||||
|
||||
// Resolves the host TLS trust bundle without weakening certificate
|
||||
@@ -76,29 +49,13 @@ HostCaBundleResolution ConfigureHostCaBundlePathMappings();
|
||||
|
||||
const char* HostCaBundleStatusName(HostCaBundleStatus status);
|
||||
|
||||
// Maps an Android-style virtual path to its Flatpak sandbox equivalent.
|
||||
//
|
||||
// Example:
|
||||
// "/data/user/0/com.roblox.client/files/logs" →
|
||||
// "/home/user/.var/app/org.vinegarhq.Sober/data/sober/logs"
|
||||
//
|
||||
// Args:
|
||||
// android_path: Absolute path as seen by the Bionic library.
|
||||
//
|
||||
// Returns:
|
||||
// Translated host path. Returns android_path unchanged if no mapping
|
||||
// is registered for it.
|
||||
// Applies the longest matching Android-to-host path prefix. Unmapped paths are
|
||||
// returned unchanged.
|
||||
std::string TranslatePath(const std::string& android_path);
|
||||
|
||||
// Registers a path prefix mapping used by TranslatePath.
|
||||
//
|
||||
// Args:
|
||||
// android_prefix: Android path prefix to intercept.
|
||||
// host_prefix: Replacement prefix on the host filesystem.
|
||||
void RegisterPathMapping(const std::string& android_prefix,
|
||||
const std::string& host_prefix);
|
||||
|
||||
// Removes all registered path mappings. Primarily for use in tests.
|
||||
void ClearPathMappings();
|
||||
|
||||
} // namespace libc_shim
|
||||
@@ -123,4 +80,4 @@ ssize_t mocktail___readlink_chk(const char* path, char* buf, size_t len,
|
||||
size_t buf_len);
|
||||
}
|
||||
|
||||
#endif // SOBER_TEST_LIBC_SHIM_LIBC_SHIM_H_
|
||||
#endif // MOCKTAIL_LIBC_SHIM_LIBC_SHIM_H_
|
||||
+5
-81
@@ -1,29 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// linker/linker.h — ELF Bionic-compatible shared library loader.
|
||||
//
|
||||
// Provides a minimal interface for loading Android ELF shared libraries
|
||||
// (.so files compiled for Bionic libc / Android ABI) into a Linux process
|
||||
// address space, resolving dependencies and exporting a symbol table.
|
||||
//
|
||||
// Design notes:
|
||||
// - Uses dlopen(3) under the hood for system libraries.
|
||||
// - For Bionic-ABI libraries (libroblox.so), manual ELF parsing and
|
||||
// mmap(2)-based loading is required; this header exposes that interface.
|
||||
// - All paths follow POSIX conventions.
|
||||
|
||||
#ifndef MOCKTAIL_LINKER_LINKER_H_
|
||||
#define MOCKTAIL_LINKER_LINKER_H_
|
||||
|
||||
@@ -34,9 +8,7 @@
|
||||
|
||||
namespace linker {
|
||||
|
||||
// Opaque handle returned by LoadLibrary. Callers must not interpret the
|
||||
// pointer value; it is only valid as an argument to ResolveSymbol or
|
||||
// UnloadLibrary.
|
||||
// Opaque; valid only with this linker's resolve/unload functions.
|
||||
using LibraryHandle = void*;
|
||||
using SymbolMap = std::unordered_map<std::string, void*>;
|
||||
using AndroidLibraryLoadObserver = bool (*)(void* context,
|
||||
@@ -50,59 +22,27 @@ struct ProgramHeaderValidation {
|
||||
explicit operator bool() const noexcept { return valid; }
|
||||
};
|
||||
|
||||
// AddSyntheticLibrary — registers one Android SONAME and only the exports
|
||||
// owned by that library. Dependencies of subsequently loaded Android ELF
|
||||
// files resolve these symbols through mcpelauncher-linker.
|
||||
LibraryHandle AddSyntheticLibrary(const std::string& soname,
|
||||
const SymbolMap& exports);
|
||||
|
||||
// RegisterSyntheticSymbol — stages or adds one export to a specific Android
|
||||
// SONAME. If the synthetic library is already loaded, its symbol table is
|
||||
// updated in place.
|
||||
// Updates an already loaded library in place.
|
||||
void RegisterSyntheticSymbol(const std::string& soname,
|
||||
const std::string& name, void* address);
|
||||
|
||||
// Registers Android Bionic thread-local and synchronization ABIs only
|
||||
// for synthetic libc.so. Host code keeps its glibc implementations.
|
||||
// These adapters belong to their synthetic SONAME, never the host namespace.
|
||||
void RegisterBionicPthreadKeyRuntimeForLibc();
|
||||
|
||||
// Registers Android's DSO-aware __register_atfork entrypoint only for
|
||||
// synthetic libc.so. The host pthread bridge preserves callback order but
|
||||
// cannot unregister callbacks when a guest DSO unloads.
|
||||
void RegisterBionicAtForkRuntimeForLibc();
|
||||
|
||||
// Registers Android LP64 positioned I/O and seek entrypoints only for
|
||||
// synthetic libc.so. The bridge relies on the x86-64 host's 64-bit
|
||||
// off_t contract and never exposes host large-file feature-macro aliases.
|
||||
void RegisterBionicLargeFileRuntimeForLibc();
|
||||
|
||||
// Registers host-independent implementations of Android libc exports that
|
||||
// are not uniformly supplied by glibc and musl. Every symbol remains owned by
|
||||
// synthetic libc.so and preserves the Android x86-64 ABI.
|
||||
void RegisterBionicHostLibcRuntimeForLibc();
|
||||
|
||||
// Registers Bionic sysconf name translation only for synthetic libc.so.
|
||||
// Bionic and glibc use different integer values for sysconf names.
|
||||
void RegisterBionicSysconfRuntimeForLibc();
|
||||
|
||||
// Registers the Android LP64 sigaction layout adapter only for libc.so.
|
||||
void RegisterBionicSignalRuntimeForLibc();
|
||||
|
||||
// Registers the LP64 Bionic FILE/__sF ABI and host stdio translation only for
|
||||
// synthetic libc.so.
|
||||
void RegisterBionicStdioRuntimeForLibc();
|
||||
|
||||
// Restores mcpelauncher-linker's own libdl exports after legacy host-symbol
|
||||
// discovery. Android dlopen/dlsym must never escape into glibc.
|
||||
// Android dlopen/dlsym must not escape into glibc.
|
||||
void RegisterBionicDynamicLoaderForLibdl();
|
||||
|
||||
// GetSyntheticLibrarySymbols — returns a snapshot of one SONAME's exports.
|
||||
// The copy is safe to inspect while other libraries are being registered.
|
||||
SymbolMap GetSyntheticLibrarySymbols(const std::string& soname);
|
||||
|
||||
// UpdateAndroidLibraryPath — configures the Bionic linker's dependency search
|
||||
// path. Multiple directories use the same colon-separated syntax as
|
||||
// LD_LIBRARY_PATH.
|
||||
void UpdateAndroidLibraryPath(const std::string& search_path);
|
||||
|
||||
// Installs the single process owner that validates or adapts a real Android
|
||||
@@ -112,18 +52,12 @@ bool SetAndroidLibraryLoadObserver(AndroidLibraryLoadObserver observer,
|
||||
void* context);
|
||||
void ClearAndroidLibraryLoadObserver(void* context);
|
||||
|
||||
// OpenAndroidLibrary — loads a real Android ELF and registers its handle under
|
||||
// logical_name. The containing directory is added to the Bionic dependency
|
||||
// search path before loading.
|
||||
LibraryHandle OpenAndroidLibrary(const std::string& real_path,
|
||||
const std::string& logical_name);
|
||||
|
||||
// Legacy compatibility bridge. New code should use AddSyntheticLibrary or
|
||||
// OpenAndroidLibrary so real files and synthetic SONAMEs cannot be confused.
|
||||
LibraryHandle LoadLibrary(const std::string& real_path,
|
||||
const std::string& host_alias);
|
||||
|
||||
// ResolveSymbol — looks up an exported symbol in a loaded library.
|
||||
void* ResolveSymbol(LibraryHandle handle, const std::string& symbol_name);
|
||||
|
||||
// Crashpad execution is intentionally outside Mocktail's supported JNI
|
||||
@@ -132,24 +66,15 @@ void* ResolveSymbol(LibraryHandle handle, const std::string& symbol_name);
|
||||
bool IsBlockedRobloxCrashReportNativeSymbol(
|
||||
std::string_view symbol_name) noexcept;
|
||||
|
||||
// UnloadLibrary — releases resources associated with a loaded library.
|
||||
void UnloadLibrary(LibraryHandle handle);
|
||||
|
||||
// Legacy compatibility bridge used by the current monolithic startup path.
|
||||
// New code should use RegisterSyntheticSymbol and assign every export to its
|
||||
// owning SONAME.
|
||||
void RegisterSymbol(const std::string& name, void* addr);
|
||||
|
||||
// Returns the legacy accumulated symbol table. It remains available until the
|
||||
// existing startup path is migrated to per-SONAME maps.
|
||||
const SymbolMap& GetBionicSymbols();
|
||||
|
||||
// Returns mcpelauncher-linker's Bionic dl_iterate_phdr entrypoint. Android
|
||||
// unwinders must not receive glibc's host implementation/layout.
|
||||
// Android unwinders must not receive glibc's implementation or layout.
|
||||
void* BionicDlIteratePhdrAddress();
|
||||
|
||||
// Confirms that the Bionic program-header iterator can see a manually loaded
|
||||
// Android ELF, including the unwind metadata needed for C++ exceptions.
|
||||
ProgramHeaderValidation ValidateBionicProgramHeaders(LibraryHandle handle);
|
||||
|
||||
// Returns the mapped ELF base for a loaded Android library alias. The lookup
|
||||
@@ -157,7 +82,6 @@ ProgramHeaderValidation ValidateBionicProgramHeaders(LibraryHandle handle);
|
||||
// alias or a host-dlopen library without Bionic image metadata.
|
||||
std::uintptr_t FindLoadedAndroidLibraryBase(const std::string& logical_name);
|
||||
|
||||
// SymbolTable — global registry of alias → handle mappings.
|
||||
const std::unordered_map<std::string, LibraryHandle>& GetSymbolTable();
|
||||
|
||||
} // namespace linker
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_AUDIO_AUDIO_SINK_H_
|
||||
#define MOCKTAIL_AUDIO_AUDIO_SINK_H_
|
||||
|
||||
@@ -22,9 +8,7 @@
|
||||
|
||||
namespace mocktail::audio {
|
||||
|
||||
// Interleaved PCM formats accepted at the host audio boundary. Endianness is
|
||||
// explicit because Android x86-64 producers use little-endian PCM regardless
|
||||
// of the host implementation chosen by SDL.
|
||||
// Android producers supply little-endian interleaved PCM.
|
||||
enum class PcmSampleFormat {
|
||||
kUnsigned8,
|
||||
kSigned16LittleEndian,
|
||||
@@ -41,11 +25,9 @@ struct PcmSpec {
|
||||
using AudioBufferReleaseCallback = void (*)(void* context, const void* data,
|
||||
std::size_t size_bytes);
|
||||
|
||||
// A PCM submission. With no release callback, Enqueue() copies the bytes
|
||||
// before returning. With a release callback, the sink may borrow the buffer;
|
||||
// the caller must keep it valid until the callback runs. A successful
|
||||
// submission invokes the callback exactly once, including when Clear() or
|
||||
// Shutdown() discards queued audio. A failed submission never invokes it.
|
||||
// Without a callback Enqueue copies the bytes. With one, a successful Enqueue
|
||||
// borrows them until exactly one release callback, including on Clear or
|
||||
// Shutdown. On failure the callback is not invoked.
|
||||
struct PcmBuffer {
|
||||
const void* data = nullptr;
|
||||
std::size_t size_bytes = 0;
|
||||
@@ -57,9 +39,7 @@ Status ValidatePcmSpec(const PcmSpec& spec);
|
||||
std::size_t BytesPerSample(PcmSampleFormat format);
|
||||
std::size_t BytesPerFrame(const PcmSpec& spec);
|
||||
|
||||
// Thread-safe PCM playback contract. Implementations perform device format
|
||||
// conversion and resampling through their host audio library; callers always
|
||||
// submit data in source_spec().
|
||||
// Thread-safe; callers submit source_spec(), and the backend converts it.
|
||||
class AudioSink {
|
||||
public:
|
||||
virtual ~AudioSink() = default;
|
||||
@@ -68,15 +48,14 @@ class AudioSink {
|
||||
virtual Status Enqueue(const PcmBuffer& buffer) = 0;
|
||||
virtual Status Pause() = 0;
|
||||
virtual Status Resume() = 0;
|
||||
// Linear gain is delegated to the host audio library. Zero mutes, one is
|
||||
// unity gain, and negative or non-finite values are rejected.
|
||||
// Zero mutes; one is unity; negative and non-finite values are invalid.
|
||||
virtual Status SetGain(float linear_gain) = 0;
|
||||
virtual Status Flush() = 0;
|
||||
virtual Status Clear() = 0;
|
||||
virtual Status GetQueuedBytes(std::size_t* size_bytes) const = 0;
|
||||
|
||||
// Idempotent. It waits for in-flight API calls and releases all borrowed
|
||||
// buffers before returning. Calls started after shutdown fail closed.
|
||||
// Idempotent. Waits for in-flight calls and borrowed buffers; later calls
|
||||
// fail closed.
|
||||
virtual void Shutdown() = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_AUDIO_FMOD_JAVA_AUDIO_RUNTIME_H_
|
||||
#define MOCKTAIL_AUDIO_FMOD_JAVA_AUDIO_RUNTIME_H_
|
||||
|
||||
@@ -23,14 +9,10 @@
|
||||
|
||||
namespace mocktail::audio {
|
||||
|
||||
// org.fmod.AudioDevice is an ordinary Java object. The JNI boundary passes
|
||||
// its jobject value through this opaque key without making the audio layer
|
||||
// depend on JNI headers or retain a JNI reference.
|
||||
// Opaque jobject identity; the audio layer never retains a JNI reference.
|
||||
using FmodJavaAudioDeviceIdentity = const void*;
|
||||
|
||||
// A factory returns a paused sink with exactly source_spec. Production uses
|
||||
// SDL3; tests can inject a deterministic sink without opening a host device.
|
||||
// factory_context must remain valid until the runtime is shut down.
|
||||
// Returns a paused sink. factory_context must outlive the runtime.
|
||||
using FmodJavaAudioSinkFactory = Status (*)(
|
||||
void* factory_context, const PcmSpec& source_spec,
|
||||
std::unique_ptr<AudioSink>* sink);
|
||||
@@ -44,8 +26,7 @@ struct FmodJavaAudioRuntimeOptions {
|
||||
std::size_t max_buffer_bytes_per_device = 64U * 1024U * 1024U;
|
||||
};
|
||||
|
||||
// Content-free counters suitable for readiness logs. They never expose PCM,
|
||||
// JNI identities, or guest pointers.
|
||||
// Contains no PCM, JNI identities, or guest pointers.
|
||||
struct FmodJavaAudioRuntimeStats {
|
||||
std::uint64_t init_attempts = 0;
|
||||
std::uint64_t initialized_devices = 0;
|
||||
@@ -65,18 +46,9 @@ struct FmodJavaAudioRuntimeStats {
|
||||
std::size_t pending_bytes = 0;
|
||||
};
|
||||
|
||||
// Thread-safe implementation of the APK's exact Java playback contract:
|
||||
//
|
||||
// AudioDevice.init(channels, sampleRate, blockSize, blockCount)Z
|
||||
// AudioDevice.write(byte[], length)V
|
||||
// AudioDevice.close()V
|
||||
//
|
||||
// Init() allocates blockCount fixed slots of blockSize frames. Every successful
|
||||
// Write() copies guest bytes synchronously into one slot, then lends that stable
|
||||
// storage to AudioSink without a second PCM copy. FmodJavaAudioRuntime performs
|
||||
// no per-write allocation for buffer storage or release ownership. A producer
|
||||
// waits with AudioTrack-style blocking backpressure when all slots are borrowed
|
||||
// instead of growing memory or dropping a block.
|
||||
// Fixed slots avoid per-write allocation. Write copies into a slot, then lends
|
||||
// it to AudioSink; a full pool applies blocking backpressure instead of
|
||||
// growing memory or dropping audio.
|
||||
class FmodJavaAudioRuntime final {
|
||||
public:
|
||||
explicit FmodJavaAudioRuntime(
|
||||
@@ -94,8 +66,7 @@ class FmodJavaAudioRuntime final {
|
||||
|
||||
FmodJavaAudioRuntimeStats GetStats() const;
|
||||
|
||||
// Idempotent. Prevents new devices/writes, shuts down every sink, and waits
|
||||
// for every borrowed owned buffer to be released before returning.
|
||||
// Waits for every borrowed buffer to be released.
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_AUDIO_FMOD_JNI_AUDIO_BRIDGE_H_
|
||||
#define MOCKTAIL_AUDIO_FMOD_JNI_AUDIO_BRIDGE_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_AUDIO_OPENSL_ABI_H_
|
||||
#define MOCKTAIL_AUDIO_OPENSL_ABI_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_AUDIO_OPENSL_PLAYBACK_RUNTIME_H_
|
||||
#define MOCKTAIL_AUDIO_OPENSL_PLAYBACK_RUNTIME_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_AUDIO_OPENSL_RUNTIME_ABI_H_
|
||||
#define MOCKTAIL_AUDIO_OPENSL_RUNTIME_ABI_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_AUDIO_OPENSL_SIMPLE_BUFFER_QUEUE_H_
|
||||
#define MOCKTAIL_AUDIO_OPENSL_SIMPLE_BUFFER_QUEUE_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_AUDIO_ROBLOX_OUTPUT_DEVICE_BRIDGE_H_
|
||||
#define MOCKTAIL_AUDIO_ROBLOX_OUTPUT_DEVICE_BRIDGE_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_AUDIO_SDL_AUDIO_SINK_H_
|
||||
#define MOCKTAIL_AUDIO_SDL_AUDIO_SINK_H_
|
||||
|
||||
@@ -25,9 +11,7 @@
|
||||
|
||||
namespace mocktail::audio {
|
||||
|
||||
// SDL documents subsystem initialization and shutdown as main-thread-only.
|
||||
// The process composition root owns this lifetime; audio workers only create
|
||||
// streams while the subsystem is active.
|
||||
// SDL requires subsystem startup and shutdown on the main thread.
|
||||
Status InitializeSdlAudioSubsystem();
|
||||
Status ShutdownSdlAudioSubsystem();
|
||||
|
||||
@@ -36,50 +20,37 @@ struct SdlPlaybackDevice {
|
||||
std::string name;
|
||||
};
|
||||
|
||||
// Lists physical SDL playback devices. The abstract `default` target is not a
|
||||
// physical entry and is therefore intentionally absent from this vector.
|
||||
// The virtual `default` target is not returned.
|
||||
Status ListSdlPlaybackDevices(std::vector<SdlPlaybackDevice>* devices);
|
||||
|
||||
// Resolves `default` or one exact physical device name. This pure selection
|
||||
// step is separate from SDL enumeration so configuration behavior is directly
|
||||
// testable.
|
||||
Status ResolveSdlPlaybackDevice(
|
||||
std::string_view requested,
|
||||
const std::vector<SdlPlaybackDevice>& available_devices,
|
||||
std::uint32_t* playback_device_id, std::string* resolved_name);
|
||||
|
||||
// Sets the process playback target used by every subsequently created FMOD
|
||||
// Java and OpenSL sink. It must run after SDL audio initialization and before
|
||||
// the first sink is opened.
|
||||
// Must run after SDL audio initialization and before the first sink opens.
|
||||
Status ConfigureSdlPlaybackDevice(
|
||||
std::string_view requested,
|
||||
std::vector<SdlPlaybackDevice>* available_devices,
|
||||
std::string* resolved_name);
|
||||
|
||||
// Returns the process playback target currently used by new sinks. The
|
||||
// physical ID is zero for SDL's system-default route.
|
||||
// Device ID zero means the system default.
|
||||
Status GetConfiguredSdlPlaybackDevice(std::uint32_t* playback_device_id,
|
||||
std::string* resolved_name);
|
||||
|
||||
// Atomically migrates every live FMOD Java and OpenSL stream to one physical
|
||||
// SDL device, or to the system default when playback_device_id is zero. New
|
||||
// sinks inherit the same target. Existing queued PCM stays in its stream.
|
||||
// Migrates live streams without dropping queued PCM. New sinks inherit it.
|
||||
Status SwitchSdlPlaybackDevice(std::uint32_t playback_device_id,
|
||||
std::string* resolved_name);
|
||||
|
||||
struct SdlAudioSinkOptions {
|
||||
PcmSpec source_spec;
|
||||
|
||||
// Zero selects the process playback target configured above (the SDL
|
||||
// default until explicitly configured). A nonzero ID bypasses that target.
|
||||
// Zero selects the configured process target.
|
||||
std::uint32_t playback_device_id = 0;
|
||||
bool start_paused = true;
|
||||
};
|
||||
|
||||
// Opens a real SDL 3.4+ playback device and its bound SDL_AudioStream. The SDL
|
||||
// audio subsystem must already be owned by InitializeSdlAudioSubsystem(). SDL
|
||||
// owns all format conversion, resampling, and borrowed-buffer consumption.
|
||||
// On failure, *sink remains null.
|
||||
// SDL owns conversion, resampling, and borrowed-buffer consumption.
|
||||
Status CreateSdlAudioSink(const SdlAudioSinkOptions& options,
|
||||
std::unique_ptr<AudioSink>* sink);
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_GRAPHICS_ANDROID_VULKAN_WSI_ADAPTER_H_
|
||||
#define MOCKTAIL_GRAPHICS_ANDROID_VULKAN_WSI_ADAPTER_H_
|
||||
|
||||
@@ -26,9 +12,7 @@
|
||||
namespace mocktail {
|
||||
namespace graphics {
|
||||
|
||||
// Vulkan VkResult values are a stable signed 32-bit ABI. Keeping the Android
|
||||
// boundary independent of the optional Vulkan SDK lets capability-only builds
|
||||
// continue to compile with SDL's opaque Vulkan handles.
|
||||
// Stable signed 32-bit ABI, independent of the optional Vulkan SDK.
|
||||
using AndroidVulkanResult = VkResult;
|
||||
|
||||
inline constexpr AndroidVulkanResult kAndroidVulkanSuccess =
|
||||
@@ -43,43 +27,29 @@ inline constexpr std::uint64_t kHostImageAcquireWatchdogTimeoutNs =
|
||||
inline constexpr char kAndroidSurfaceExtension[] =
|
||||
"VK_KHR_android_surface";
|
||||
|
||||
// Desktop compositors can report a valid acquired/presented image as
|
||||
// suboptimal while a fullscreen configure settles. The Android client path
|
||||
// used by Roblox treats that positive success code as a hard error, so the
|
||||
// compatibility boundary exposes it as the equivalent VK_SUCCESS result.
|
||||
// Roblox treats VK_SUBOPTIMAL_KHR as a hard error, so expose it as success.
|
||||
VkResult NormalizeAndroidSwapchainResult(VkResult result);
|
||||
|
||||
// Android requests an infinite image-acquire wait, but a lost Wayland/X11
|
||||
// compositor wakeup would then block Roblox's RenderJob forever. Only the
|
||||
// infinite guest request is bounded; explicit finite Vulkan timeouts retain
|
||||
// their original contract.
|
||||
// Bounds only infinite acquire waits so a lost compositor wakeup cannot hang.
|
||||
std::uint64_t BoundHostImageAcquireTimeout(std::uint64_t requested_timeout);
|
||||
bool IsHostImageAcquireWatchdogTimeout(std::uint64_t requested_timeout,
|
||||
VkResult host_result);
|
||||
VkResult NormalizeHostImageAcquireResult(std::uint64_t requested_timeout,
|
||||
VkResult host_result);
|
||||
|
||||
// Infinite fence/timeline waits retain their guest-visible semantics, but are
|
||||
// issued to the host in finite slices so a stalled renderer produces evidence
|
||||
// while it remains blocked. VK_TIMEOUT from a slice is never returned to the
|
||||
// Android client as a completed wait.
|
||||
// Infinite guest waits use finite host slices without exposing slice timeouts.
|
||||
std::uint64_t BoundHostSynchronizationWaitTimeout(
|
||||
std::uint64_t requested_timeout);
|
||||
bool ShouldContinueHostSynchronizationWait(std::uint64_t requested_timeout,
|
||||
VkResult host_result);
|
||||
|
||||
// Rewrites an Android VkInstance extension request for the host WSI. The
|
||||
// returned storage owns its strings and can be used to build the
|
||||
// ppEnabledExtensionNames array passed to the host vkCreateInstance call.
|
||||
// Returned storage owns the translated extension names.
|
||||
Status TranslateAndroidVulkanInstanceExtensions(
|
||||
const std::vector<std::string>& android_extensions,
|
||||
const std::vector<std::string>& host_wsi_extensions,
|
||||
std::vector<std::string>* host_extensions);
|
||||
|
||||
// Android WSI boundary. vkCreateAndroidSurfaceKHR-compatible exports can
|
||||
// delegate here after vkCreateInstance has used the translated extension list.
|
||||
// The Android native-window member is intentionally ignored: SDL owns the real
|
||||
// host window and is the only component allowed to create its VkSurfaceKHR.
|
||||
// Ignores the guest native-window field; SDL alone creates the host surface.
|
||||
class AndroidVulkanWsiAdapter final {
|
||||
public:
|
||||
using PresentCallback = void (*)(void* user_data);
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_GRAPHICS_ANGLE_PROBE_H_
|
||||
#define MOCKTAIL_GRAPHICS_ANGLE_PROBE_H_
|
||||
|
||||
|
||||
@@ -1,25 +1,5 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Exact-path loader for Mocktail's Bionic libEGL adapter.
|
||||
//
|
||||
// A host EGL implementation may have the Android SONAME "libEGL.so" too
|
||||
// (Chromium ANGLE does). Loading by SONAME after SDL/ANGLE starts can then
|
||||
// return the host implementation and make Android code create a second EGL
|
||||
// surface for one native window. This adapter opens the Mocktail
|
||||
// bridge beside the executable and exposes only its EGL exports for the
|
||||
// synthetic Bionic libEGL.so dependency.
|
||||
// Loading by SONAME can select host ANGLE instead of the Bionic adapter. This
|
||||
// bridge therefore opens the library beside the executable by exact path.
|
||||
|
||||
#ifndef MOCKTAIL_GRAPHICS_BIONIC_EGL_BRIDGE_H_
|
||||
#define MOCKTAIL_GRAPHICS_BIONIC_EGL_BRIDGE_H_
|
||||
@@ -37,9 +17,7 @@ public:
|
||||
BionicEglBridge(const BionicEglBridge &) = delete;
|
||||
BionicEglBridge &operator=(const BionicEglBridge &) = delete;
|
||||
|
||||
// Loads $ORIGIN/libEGL.so by its exact absolute path. On success, the
|
||||
// handle intentionally remains live for the process lifetime because the
|
||||
// Bionic linker retains the exported function addresses.
|
||||
// The handle stays live because the Bionic linker retains its exports.
|
||||
bool Load();
|
||||
|
||||
bool IsLoaded() const { return handle_ != nullptr; }
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_GRAPHICS_GRAPHICS_BACKEND_H_
|
||||
#define MOCKTAIL_GRAPHICS_GRAPHICS_BACKEND_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_GRAPHICS_PRESENT_MODE_POLICY_H_
|
||||
#define MOCKTAIL_GRAPHICS_PRESENT_MODE_POLICY_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_GRAPHICS_SDL_VULKAN_WSI_H_
|
||||
#define MOCKTAIL_GRAPHICS_SDL_VULKAN_WSI_H_
|
||||
|
||||
@@ -30,9 +16,8 @@
|
||||
namespace mocktail {
|
||||
namespace graphics {
|
||||
|
||||
// Thin host WSI scaffold. It does not create a VkInstance, device, swapchain,
|
||||
// renderer, or allocator. A future Android Vulkan adapter may translate
|
||||
// vkCreateAndroidSurfaceKHR into CreateSurface after rewriting extensions.
|
||||
// Provides SDL's host WSI entry points. Instance, device, swapchain, renderer,
|
||||
// and allocator ownership stays with the caller.
|
||||
class SdlVulkanWsi final {
|
||||
public:
|
||||
SdlVulkanWsi() = default;
|
||||
|
||||
@@ -1,36 +1,18 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_GRAPHICS_TEXT_OVERLAY_FRAME_H_
|
||||
#define MOCKTAIL_GRAPHICS_TEXT_OVERLAY_FRAME_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
// Stable process-local ABI between the host input runtime in the executable
|
||||
// and libvulkan.so, which is loaded as a separate Android compatibility DSO.
|
||||
// Pixels are tightly packed RGBA8. The producer owns and securely clears its
|
||||
// storage; consumers must copy a matching revision before returning.
|
||||
// Process-local ABI with libvulkan.so. Pixels are RGBA8; consumers must copy a
|
||||
// matching revision before the producer clears its storage.
|
||||
struct MocktailTextOverlayFrameInfo {
|
||||
static constexpr std::uint32_t kAbiVersion = 2;
|
||||
|
||||
std::uint32_t abi_version = kAbiVersion;
|
||||
std::uint32_t visible = 0;
|
||||
std::uint64_t revision = 0;
|
||||
// x/y/width/height use the host's logical input coordinate space. These
|
||||
// dimensions let a Vulkan consumer map that space to the swapchain's pixel
|
||||
// extent without assuming a 1:1 high-DPI scale.
|
||||
// Coordinates are logical, not swapchain pixels.
|
||||
std::uint32_t coordinate_width = 0;
|
||||
std::uint32_t coordinate_height = 0;
|
||||
std::int32_t x = 0;
|
||||
@@ -43,9 +25,7 @@ struct MocktailTextOverlayFrameInfo {
|
||||
|
||||
extern "C" {
|
||||
|
||||
// Lock-free conservative hint for the Vulkan present fast path. A false
|
||||
// result guarantees that no drawable overlay is currently published. A true
|
||||
// result only means that the synchronized query/copy path must decide.
|
||||
// false guarantees no overlay; true still requires a synchronized query.
|
||||
bool mocktail_text_overlay_may_present();
|
||||
bool mocktail_text_overlay_query(MocktailTextOverlayFrameInfo* frame);
|
||||
bool mocktail_text_overlay_copy(std::uint64_t revision, void* rgba,
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
// Licensed under the Apache License, Version 2.0.
|
||||
|
||||
#ifndef MOCKTAIL_GRAPHICS_VULKAN_ABI_H_
|
||||
#define MOCKTAIL_GRAPHICS_VULKAN_ABI_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_GRAPHICS_VULKAN_TEXT_OVERLAY_COMPOSITOR_H_
|
||||
#define MOCKTAIL_GRAPHICS_VULKAN_TEXT_OVERLAY_COMPOSITOR_H_
|
||||
|
||||
@@ -22,13 +8,8 @@
|
||||
namespace mocktail {
|
||||
namespace graphics {
|
||||
|
||||
// Composites the process-local RGBA text surface into application-owned
|
||||
// swapchain images. The adapter retains ownership of every Vulkan object it
|
||||
// registers. DestroySwapchain and DestroyDevice must be called before the
|
||||
// corresponding host Vulkan destroy function.
|
||||
//
|
||||
// An unsupported device or swapchain remains a valid registration failure:
|
||||
// QueuePresent then forwards the unmodified VkPresentInfoKHR to fallback.
|
||||
// Registered Vulkan objects remain caller-owned and must be unregistered
|
||||
// before host destruction. Unsupported registrations fall back cleanly.
|
||||
class VulkanTextOverlayCompositor final {
|
||||
public:
|
||||
VulkanTextOverlayCompositor();
|
||||
@@ -38,10 +19,8 @@ class VulkanTextOverlayCompositor final {
|
||||
VulkanTextOverlayCompositor& operator=(const VulkanTextOverlayCompositor&) =
|
||||
delete;
|
||||
|
||||
// enabled_features describes the features actually enabled by
|
||||
// vkCreateDevice, not merely the features supported by the physical device.
|
||||
// The supplied proc-address callbacks must bypass the Android-facing Vulkan
|
||||
// adapter and resolve host functions directly.
|
||||
// enabled_features must match vkCreateDevice. Proc callbacks resolve host
|
||||
// functions directly, bypassing the Android adapter.
|
||||
bool RegisterDevice(VkInstance instance, VkPhysicalDevice physical_device,
|
||||
VkDevice device, std::uint32_t api_version,
|
||||
const char* const* enabled_extensions,
|
||||
@@ -61,10 +40,7 @@ class VulkanTextOverlayCompositor final {
|
||||
const VkImage* images, std::uint32_t image_count);
|
||||
void DestroySwapchain(VkDevice device, VkSwapchainKHR swapchain);
|
||||
|
||||
// Serializes adapter-mediated submit, sparse-bind, present, and idle
|
||||
// operations on the exact queue range imported by libplacebo. Other
|
||||
// VkQueues remain independent, including the inactive-overlay fast path on
|
||||
// a non-imported queue.
|
||||
// Adapter operations serialize only queues imported by libplacebo.
|
||||
VkResult QueueSubmit(VkQueue queue, std::uint32_t submit_count,
|
||||
const VkSubmitInfo* submits, VkFence fence,
|
||||
PFN_vkQueueSubmit fallback);
|
||||
@@ -77,10 +53,7 @@ class VulkanTextOverlayCompositor final {
|
||||
VkResult QueueWaitIdle(VkQueue queue, PFN_vkQueueWaitIdle fallback);
|
||||
VkResult DeviceWaitIdle(VkDevice device, PFN_vkDeviceWaitIdle fallback);
|
||||
|
||||
// Always invokes fallback when it is non-null. The original wait semaphores
|
||||
// are forwarded unchanged until the compositor successfully submits the
|
||||
// wait-collapse bridge; after that point only compositor-owned semaphores
|
||||
// are passed to fallback.
|
||||
// After wait collapse, fallback receives only compositor-owned semaphores.
|
||||
VkResult QueuePresent(VkQueue queue, const VkPresentInfoKHR* present_info,
|
||||
PFN_vkQueuePresentKHR fallback);
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_PLATFORM_ANDROID_LOG_OBSERVER_H_
|
||||
#define MOCKTAIL_PLATFORM_ANDROID_LOG_OBSERVER_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_PLATFORM_DISPLAY_REFRESH_CAPABILITIES_H_
|
||||
#define MOCKTAIL_PLATFORM_DISPLAY_REFRESH_CAPABILITIES_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_PLATFORM_PLATFORM_RUNTIME_H_
|
||||
#define MOCKTAIL_PLATFORM_PLATFORM_RUNTIME_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_PLATFORM_SDL_APPLICATION_METADATA_H_
|
||||
#define MOCKTAIL_PLATFORM_SDL_APPLICATION_METADATA_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_PLATFORM_SDL_EVENT_CONVERTER_H_
|
||||
#define MOCKTAIL_PLATFORM_SDL_EVENT_CONVERTER_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_PLATFORM_SDL_PLATFORM_RUNTIME_H_
|
||||
#define MOCKTAIL_PLATFORM_SDL_PLATFORM_RUNTIME_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_PLATFORM_SDL_WINDOW_ICON_H_
|
||||
#define MOCKTAIL_PLATFORM_SDL_WINDOW_ICON_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_PLATFORM_TEXT_CLIPBOARD_H_
|
||||
#define MOCKTAIL_PLATFORM_TEXT_CLIPBOARD_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_MOCKTAIL_SHA256_H_
|
||||
#define MOCKTAIL_MOCKTAIL_SHA256_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_STATUS_H_
|
||||
#define MOCKTAIL_STATUS_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_AUTH_RUNTIME_COMPOSITION_H_
|
||||
#define MOCKTAIL_RUNTIME_AUTH_RUNTIME_COMPOSITION_H_
|
||||
|
||||
@@ -40,9 +26,7 @@ enum class AuthRuntimeStatus {
|
||||
kUnavailable,
|
||||
};
|
||||
|
||||
// Process-local ownership for the canonical .ROBLOSECURITY header. The class
|
||||
// is move-only and clears its backing allocation before release.
|
||||
// Callers must never log the value returned by view() or c_str().
|
||||
// Move-only credential storage that clears its allocation. Never log its view.
|
||||
class SecureRobloxCredential final {
|
||||
public:
|
||||
SecureRobloxCredential() = default;
|
||||
@@ -64,14 +48,10 @@ class SecureRobloxCredential final {
|
||||
std::vector<char> bytes_;
|
||||
};
|
||||
|
||||
// Clears a transient string that contained derived credential material.
|
||||
void SecurelyClearString(std::string* value);
|
||||
|
||||
// Binds the production pseudo-VM to the exact credential resolved by the
|
||||
// authentication preflight. The binding is intentionally non-movable:
|
||||
// it must be created only after its credential reaches its final address and
|
||||
// destroyed before that credential or the VM. Guest credentials block legacy
|
||||
// env/disk fallback until the sink durably accepts a native sign-in value.
|
||||
// Must be created after the credential reaches its final address and destroyed
|
||||
// before the credential or VM. Guest bindings block legacy env/disk fallback.
|
||||
class ScopedRobloxCredentialBinding final {
|
||||
public:
|
||||
ScopedRobloxCredentialBinding(jnivm::VM* jni_vm,
|
||||
@@ -93,35 +73,26 @@ class ScopedRobloxCredentialBinding final {
|
||||
jnivm::VM* jni_vm_ = nullptr;
|
||||
};
|
||||
|
||||
// Result of resolving host credentials before the Android runtime starts.
|
||||
// Credential ownership is retained only so the exact credential validated by
|
||||
// AuthService can be moved into native startup without reopening its source.
|
||||
// Retains the validated credential without reopening its source.
|
||||
struct AuthRuntimeComposition {
|
||||
AuthRuntimeStatus status = AuthRuntimeStatus::kUnavailable;
|
||||
std::shared_ptr<jnivm::VM> jni_vm;
|
||||
jnivm::RobloxAuthIdentity account_identity;
|
||||
SecureRobloxCredential credential;
|
||||
long http_status = 0;
|
||||
bool rejected_credential_retired = false;
|
||||
std::string error;
|
||||
|
||||
explicit operator bool() const { return jni_vm != nullptr; }
|
||||
};
|
||||
|
||||
// Resolves the saved Roblox session and constructs the production pseudo-VM.
|
||||
// A VM is returned only for an authenticated session or when guest startup is
|
||||
// explicitly enabled with MOCKTAIL_ALLOW_NO_COOKIE_LUA_APP. An exact HTTP 401
|
||||
// from a managed Mocktail file clears only the rejected .ROBLOSECURITY. A
|
||||
// rejected default Sober credential is suppressed by a private fingerprint
|
||||
// without modifying Sober's file. The guest policy then allows native sign-in
|
||||
// to continue. Explicit overrides, unsafe recovery, other invalid credentials,
|
||||
// and unavailable authentication still fail closed before native startup.
|
||||
// A VM requires authentication or explicit guest mode. HTTP 401/403 clears
|
||||
// only Mocktail's managed credential.
|
||||
AuthRuntimeComposition ComposeAuthRuntime(const Environment& environment,
|
||||
const RuntimePaths& paths,
|
||||
services::AuthService& auth_service);
|
||||
|
||||
// Production overload retaining the HTTP transport for credentials delivered
|
||||
// by native sign-in after startup. A persisted credential is validated before
|
||||
// its account identity is promoted into the running pseudo-VM.
|
||||
// Retains HTTP transport for native sign-in and validates persisted credentials.
|
||||
AuthRuntimeComposition ComposeAuthRuntime(
|
||||
const Environment& environment, const RuntimePaths& paths,
|
||||
services::AuthService& auth_service,
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_COMMAND_LINE_H_
|
||||
#define MOCKTAIL_RUNTIME_COMMAND_LINE_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_CRASH_REPORT_POLICY_H_
|
||||
#define MOCKTAIL_RUNTIME_CRASH_REPORT_POLICY_H_
|
||||
|
||||
@@ -21,19 +7,12 @@
|
||||
namespace mocktail {
|
||||
namespace runtime {
|
||||
|
||||
// Applies Mocktail's mandatory privacy boundary to the flat Roblox
|
||||
// client-settings override object. The policy disables native Crashpad, Java
|
||||
// crash/ANR uploads, Lua Backtrace errors, and inferred-crash submission while
|
||||
// preserving unrelated caller overrides. Unsafe values are replaced rather
|
||||
// than treated as conflicts because crash upload is not a user-configurable
|
||||
// runtime capability.
|
||||
// Disables Roblox crash uploads while preserving unrelated overrides.
|
||||
bool MergeCrashReportClientSettingsOverrides(std::string_view base_json,
|
||||
std::string* merged_json,
|
||||
std::string* error);
|
||||
|
||||
// Applies the same mandatory values to Roblox's separate AppBridge
|
||||
// fastFlagsJson channel. Only FastVariable names are inserted here;
|
||||
// Java-only client settings remain on the client-settings boundary above.
|
||||
// AppBridge accepts only the FastVariable subset of this policy.
|
||||
bool MergeCrashReportFastFlagsOverrides(std::string_view base_json,
|
||||
std::string* merged_json,
|
||||
std::string* error);
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_DEVICE_PROFILE_H_
|
||||
#define MOCKTAIL_RUNTIME_DEVICE_PROFILE_H_
|
||||
|
||||
@@ -28,9 +14,7 @@ enum class DeviceClass {
|
||||
kConsole,
|
||||
};
|
||||
|
||||
// One immutable profile keeps Roblox admission, pseudo-Android hardware
|
||||
// identity, and built-in input capabilities consistent. The guest ABI and
|
||||
// client-settings group remain Android/GoogleAndroidApp.
|
||||
// Admission changes do not change the Android guest ABI.
|
||||
struct DeviceProfile {
|
||||
std::string name;
|
||||
std::string cache_key;
|
||||
@@ -51,18 +35,14 @@ struct DeviceProfile {
|
||||
};
|
||||
|
||||
inline constexpr std::string_view kDefaultDeviceProfileName = "pc-windows-11";
|
||||
// These identifiers select Roblox server-side admission only. They never
|
||||
// replace the Android APK ABI or its GoogleAndroidApp client-settings group.
|
||||
// Transport classifier only; the guest remains GoogleAndroidApp.
|
||||
inline constexpr std::string_view kRobloxDesktopHttpUserAgent =
|
||||
"Roblox/WinInet";
|
||||
// The current Android-host playability endpoint recognizes this as console.
|
||||
// PlayStation-labelled user agents currently fall back to desktop admission,
|
||||
// so the PS5 marketing profile keeps this transport-only classifier.
|
||||
// The playability endpoint recognizes this classifier as console.
|
||||
inline constexpr std::string_view kRobloxConsoleAdmissionUserAgent =
|
||||
"Roblox/XboxOne";
|
||||
|
||||
// Accepts canonical names and the convenient pc/mobile/console aliases.
|
||||
// Returned profiles have static lifetime.
|
||||
// Accepts canonical names and pc/mobile/console aliases; result is static.
|
||||
const DeviceProfile* FindDeviceProfile(std::string_view name);
|
||||
bool IsValidDeviceProfileValue(std::string_view value, std::size_t maximum);
|
||||
std::string BuildCustomDeviceProfileCacheKey(const DeviceProfile& profile);
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef MOCKTAIL_RUNTIME_DISCORD_RPC_H_
|
||||
#define MOCKTAIL_RUNTIME_DISCORD_RPC_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "runtime/roblox_experience_presence.h"
|
||||
#include "runtime/runtime_config.h"
|
||||
|
||||
namespace mocktail {
|
||||
namespace runtime {
|
||||
|
||||
struct DiscordRpcActivity {
|
||||
std::string details;
|
||||
std::string state;
|
||||
std::optional<int64_t> start_timestamp;
|
||||
std::string large_image;
|
||||
std::string large_text;
|
||||
std::string button_label;
|
||||
std::string button_url;
|
||||
};
|
||||
|
||||
bool IsPublicDiscordJoin(const RobloxExperienceLaunchRequest& request);
|
||||
std::string BuildDiscordJoinUrl(const RobloxExperienceLaunchRequest& request);
|
||||
DiscordRpcActivity BuildDiscordRpcActivity(
|
||||
const DiscordRpcConfig& config, RobloxExperiencePresencePhase phase,
|
||||
const RobloxExperienceLaunchRequest* request, std::string place_name,
|
||||
int64_t session_started_at, std::string place_icon_url = {});
|
||||
|
||||
// Maintains a direct, unauthenticated Discord Desktop RPC connection. The
|
||||
// worker owns all network and IPC work; lifecycle notifications only replace
|
||||
// a small in-memory snapshot and never block the Roblox main thread.
|
||||
class DiscordRpcSession final {
|
||||
public:
|
||||
explicit DiscordRpcSession(DiscordRpcConfig config);
|
||||
~DiscordRpcSession();
|
||||
|
||||
DiscordRpcSession(const DiscordRpcSession&) = delete;
|
||||
DiscordRpcSession& operator=(const DiscordRpcSession&) = delete;
|
||||
|
||||
bool Start(std::string* detail = nullptr);
|
||||
void Stop();
|
||||
RobloxExperiencePresenceObserver observer();
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
static void Notify(void* context, RobloxExperiencePresencePhase phase,
|
||||
const RobloxExperienceLaunchRequest* request);
|
||||
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
|
||||
} // namespace runtime
|
||||
} // namespace mocktail
|
||||
|
||||
#endif // MOCKTAIL_RUNTIME_DISCORD_RPC_H_
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_ENVIRONMENT_H_
|
||||
#define MOCKTAIL_RUNTIME_ENVIRONMENT_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_EXTERNAL_LAUNCH_BROKER_H_
|
||||
#define MOCKTAIL_RUNTIME_EXTERNAL_LAUNCH_BROKER_H_
|
||||
|
||||
@@ -28,14 +14,10 @@ namespace runtime {
|
||||
inline constexpr std::size_t kMaximumPendingExternalLaunches = 8;
|
||||
|
||||
struct ExternalLaunchBrokerOptions {
|
||||
// Empty selects the current user's protected runtime endpoint. Tests and
|
||||
// isolated launchers may provide an explicit socket under a private
|
||||
// directory owned by the current user.
|
||||
// Empty selects the current user's protected endpoint.
|
||||
std::filesystem::path socket_path;
|
||||
std::size_t maximum_pending_launches = kMaximumPendingExternalLaunches;
|
||||
// The owner crosses configuration/bootstrap and a possible cgroup
|
||||
// re-exec before it can safely ACK. A concurrent browser click waits through
|
||||
// that bounded startup window instead of racing a not-yet-created socket.
|
||||
// Covers bootstrap and a possible cgroup re-exec.
|
||||
int forwarding_timeout_ms = 30000;
|
||||
};
|
||||
|
||||
@@ -49,16 +31,11 @@ struct ExternalLaunchSink {
|
||||
bool valid() const { return dispatch != nullptr; }
|
||||
};
|
||||
|
||||
// Resolves the per-user, per-installation endpoint. Owner resolution may
|
||||
// create only the private fallback directory; it never removes a stale
|
||||
// socket. Socket cleanup belongs exclusively to StartOwnerAfterLockAcquired
|
||||
// after the caller owns the matching Mocktail single-instance lock.
|
||||
// Resolution never removes stale sockets; only a lock-owning broker may do so.
|
||||
Status ResolveExternalLaunchSocketPath(bool owner,
|
||||
std::filesystem::path* socket_path);
|
||||
|
||||
// Owns a bounded process-local launch queue and its same-user AF_UNIX endpoint.
|
||||
// Wire requests contain only already-normalized ExperienceProtocol JSON; the
|
||||
// raw browser URI and its gameinfo ticket never cross this boundary.
|
||||
// The wire format contains normalized requests, never raw browser tickets.
|
||||
class ExternalLaunchBroker final {
|
||||
public:
|
||||
~ExternalLaunchBroker();
|
||||
@@ -68,25 +45,20 @@ class ExternalLaunchBroker final {
|
||||
ExternalLaunchBroker(ExternalLaunchBroker&&) = delete;
|
||||
ExternalLaunchBroker& operator=(ExternalLaunchBroker&&) = delete;
|
||||
|
||||
// The caller must hold the single-instance lock. Only this operation may
|
||||
// remove a stale socket left by a crashed owner. An optional initial request
|
||||
// is normalized and queued before the listener worker can accept later
|
||||
// browser clicks, preserving click order without a startup race.
|
||||
// Requires the single-instance lock. The initial request is queued before
|
||||
// the listener starts, preserving click order.
|
||||
static Status StartOwnerAfterLockAcquired(
|
||||
ExternalLaunchBrokerOptions options,
|
||||
std::shared_ptr<ExternalLaunchBroker>* broker,
|
||||
const RobloxExperienceLaunchRequest* initial_request = nullptr);
|
||||
|
||||
// Forwards one normalized request and waits for an explicit owner ACK. The
|
||||
// operation never starts a second runtime and never logs request contents.
|
||||
// Waits for an owner ACK and never logs the request.
|
||||
static Status ForwardToOwner(const ExternalLaunchBrokerOptions& options,
|
||||
const RobloxExperienceLaunchRequest& request);
|
||||
|
||||
Status QueueInitialRequest(RobloxExperienceLaunchRequest request);
|
||||
|
||||
// Dispatches at most maximum_requests in FIFO order. A failed dispatch is
|
||||
// returned to the front of the queue, so temporary downstream backpressure
|
||||
// never drops a browser launch.
|
||||
// A failed dispatch returns to the front of the FIFO queue.
|
||||
Status Drain(const ExternalLaunchSink& sink, std::size_t maximum_requests);
|
||||
|
||||
Status Shutdown();
|
||||
@@ -100,9 +72,7 @@ class ExternalLaunchBroker final {
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
|
||||
// Process-global attachment used by the composition root and the dynamic
|
||||
// ExperienceProtocol runtime. shared_ptr acquisition keeps the broker alive
|
||||
// while an external request is being drained.
|
||||
// shared_ptr acquisition keeps the active broker alive during a drain.
|
||||
Status InstallActiveExternalLaunchBroker(
|
||||
const std::shared_ptr<ExternalLaunchBroker>& broker);
|
||||
void ClearActiveExternalLaunchBroker(const ExternalLaunchBroker* broker);
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_FAILURE_DIALOG_H_
|
||||
#define MOCKTAIL_RUNTIME_FAILURE_DIALOG_H_
|
||||
|
||||
@@ -22,19 +8,16 @@
|
||||
namespace mocktail {
|
||||
namespace runtime {
|
||||
|
||||
// Returns whether an interactive launch may present a desktop failure dialog.
|
||||
// Readiness canaries and headless sessions remain strictly non-interactive.
|
||||
// Canaries and headless sessions remain non-interactive.
|
||||
bool FailureDialogsEnabled(const Environment& environment);
|
||||
|
||||
// Presents one synchronous GTK failure dialog. This is intended for startup
|
||||
// failures that happen before the crash monitor can be armed.
|
||||
bool ShowFailureDialog(const Environment& environment,
|
||||
std::string_view message);
|
||||
bool ShowWarningDialog(const Environment& environment,
|
||||
std::string_view message);
|
||||
|
||||
// Owns a small out-of-process GTK monitor. The helper is started before guest
|
||||
// threads exist and receives an explicit success disposition. If Mocktail
|
||||
// returns an error, calls _Exit(), or dies from a fatal signal, the helper
|
||||
// remains able to present the last safe user-facing message.
|
||||
// The helper starts before guest threads, so it can report errors and fatal
|
||||
// exits even when the main process can no longer show a dialog.
|
||||
class FailureDialogMonitor final {
|
||||
public:
|
||||
FailureDialogMonitor() = default;
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_FRAME_RATE_POLICY_H_
|
||||
#define MOCKTAIL_RUNTIME_FRAME_RATE_POLICY_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_GAME_MODE_H_
|
||||
#define MOCKTAIL_RUNTIME_GAME_MODE_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_GAME_SESSION_COORDINATOR_H_
|
||||
#define MOCKTAIL_RUNTIME_GAME_SESSION_COORDINATOR_H_
|
||||
|
||||
@@ -87,9 +73,9 @@ using ResumeGameFn = Status (*)(void* context, const GameSurface& surface);
|
||||
using LeaveGameFn = Status (*)(void* context);
|
||||
using ShutdownGameRuntimeFn = Status (*)(void* context);
|
||||
|
||||
// native boundary. All callbacks are synchronous and non-throwing. The
|
||||
// coordinator serializes lifecycle invocation, matching MainGameActivity's
|
||||
// single-thread executor without embedding JNI details in the policy layer.
|
||||
// These callbacks form the native boundary. They are synchronous and
|
||||
// non-throwing; the coordinator serializes lifecycle calls to match
|
||||
// MainGameActivity's single-thread executor.
|
||||
struct GameSessionCapabilities {
|
||||
void* context = nullptr;
|
||||
SetGameForegroundFn set_game_foreground = nullptr;
|
||||
@@ -171,16 +157,11 @@ struct GameSessionSnapshot {
|
||||
std::string failure_reason;
|
||||
};
|
||||
|
||||
// Fail-closed policy for the MainGameActivity game-session branch.
|
||||
//
|
||||
// SurfaceCreated must prepare a generation before SurfaceChanged can supply its
|
||||
// native window and dimensions. QueueJoinRequest and the prepared surface are
|
||||
// independent initial prerequisites; whichever completes last starts the game
|
||||
// with the current candidate surface. Initial start never calls ResumeGame.
|
||||
// Once running, SurfaceChanged updates the active surface, SurfaceDestroyed
|
||||
// pauses, and SurfaceCreated(new generation) plus SurfaceChanged resumes.
|
||||
// Candidate surfaces become active only after the corresponding native call
|
||||
// succeeds.
|
||||
// SurfaceCreated must open a generation before its matching SurfaceChanged can
|
||||
// supply a window and size. A join request and the first surface may arrive in
|
||||
// either order; initial startup calls StartGame, never ResumeGame. Once running,
|
||||
// new generations pause and resume the session. A candidate surface becomes
|
||||
// active only after its native callback succeeds.
|
||||
class GameSessionCoordinator final {
|
||||
public:
|
||||
explicit GameSessionCoordinator(GameSessionCapabilities capabilities,
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_GRAPHICS_LAUNCH_POLICY_H_
|
||||
#define MOCKTAIL_RUNTIME_GRAPHICS_LAUNCH_POLICY_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_HTTP_CLIENT_POLICY_H_
|
||||
#define MOCKTAIL_RUNTIME_HTTP_CLIENT_POLICY_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_JNIVM_PLATFORM_WEB_CALLBACKS_H_
|
||||
#define MOCKTAIL_RUNTIME_JNIVM_PLATFORM_WEB_CALLBACKS_H_
|
||||
|
||||
@@ -22,8 +8,7 @@
|
||||
namespace mocktail {
|
||||
namespace runtime {
|
||||
|
||||
// adapter kept outside the research runtime. The opaque context must be
|
||||
// the production jnivm::VM owned by the startup composition.
|
||||
// The opaque context must be the jnivm::VM owned by startup composition.
|
||||
bool SetJnivmPlatformWebCallbacks(
|
||||
void* context, std::shared_ptr<void> callback_context,
|
||||
void (*on_data_model_notification)(void*, JNIEnv*, jstring, jstring),
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_MEMORY_LIMIT_H_
|
||||
#define MOCKTAIL_RUNTIME_MEMORY_LIMIT_H_
|
||||
|
||||
@@ -53,10 +39,8 @@ struct CgroupMemoryLimitResult {
|
||||
bool active() const { return status == CgroupMemoryLimitStatus::kActive; }
|
||||
};
|
||||
|
||||
// Replaces the current process with the same command inside a transient
|
||||
// systemd user scope when cgroup v2 delegation is available. A successful
|
||||
// re-exec does not return. Systems without systemd continue with the watchdog
|
||||
// fallback and receive kUnavailable.
|
||||
// Compatibility hook for the former cgroup re-exec path. Automatic cgroup
|
||||
// scope creation is disabled, so callers continue with the watchdog fallback.
|
||||
CgroupMemoryLimitResult MaybeReexecWithCgroupMemoryLimit(
|
||||
int argc, char* const argv[], std::uint64_t limit_bytes,
|
||||
const std::vector<std::string>* reexec_arguments = nullptr);
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_OWNED_PTHREAD_H_
|
||||
#define MOCKTAIL_RUNTIME_OWNED_PTHREAD_H_
|
||||
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_PAYLOAD_UPDATE_PREFLIGHT_H_
|
||||
#define MOCKTAIL_RUNTIME_PAYLOAD_UPDATE_PREFLIGHT_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_PERFORMANCE_POLICY_H_
|
||||
#define MOCKTAIL_RUNTIME_PERFORMANCE_POLICY_H_
|
||||
|
||||
@@ -34,8 +20,7 @@ enum class PhysicsWorkerMode {
|
||||
bool ParsePhysicsWorkerMode(std::string_view value, PhysicsWorkerMode* mode);
|
||||
std::string_view PhysicsWorkerModeName(PhysicsWorkerMode mode);
|
||||
|
||||
// Makes every available physical core eligible for Roblox scheduler work.
|
||||
// At least one scheduler worker remains on malformed topology input.
|
||||
// Malformed topology still yields one worker.
|
||||
int CalculateThroughputWorkerCount(int available_physical_cores);
|
||||
|
||||
struct PerformancePolicy {
|
||||
@@ -61,25 +46,16 @@ PerformancePolicy ParsePerformancePolicy(
|
||||
std::string_view memory_limit_mb = "0", std::string_view game_mode = "auto",
|
||||
std::string_view physics_worker_mode = "auto");
|
||||
|
||||
// Counts unique physical cores available to the current process. Linux CPU
|
||||
// affinity is respected; systems without readable topology fall back to the
|
||||
// available logical CPU count.
|
||||
// Respects CPU affinity and falls back to the available logical count.
|
||||
int DetectAvailablePhysicalCoreCount();
|
||||
|
||||
// Merges the supported Roblox scheduler/rendering mode into the flat
|
||||
// client-settings override object. Disabled policy leaves existing overrides
|
||||
// intact. Conflicting explicit values fail closed instead of silently
|
||||
// replacing the caller's settings.
|
||||
// Disabled policy preserves overrides; conflicting values fail.
|
||||
bool MergePerformanceClientSettingsOverrides(const PerformancePolicy& policy,
|
||||
std::string_view base_json,
|
||||
std::string* merged_json,
|
||||
std::string* error);
|
||||
|
||||
// Applies every runtime policy in a stable order before the resulting
|
||||
// override object crosses the legacy startup boundary. The mandatory
|
||||
// HttpClient compatibility policy is applied before the mandatory crash-report
|
||||
// upload block. Neither policy can be overridden by a caller-provided client
|
||||
// setting.
|
||||
// Applies mandatory HTTP and crash policies after caller settings.
|
||||
bool MergeRuntimeClientSettingsOverrides(const FrameRatePolicy& frame_rate,
|
||||
const PerformancePolicy& performance,
|
||||
std::string_view base_json,
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_PLATFORM_CACHE_MIGRATION_H_
|
||||
#define MOCKTAIL_RUNTIME_PLATFORM_CACHE_MIGRATION_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_ROBLOX_APP_LIFECYCLE_H_
|
||||
#define MOCKTAIL_RUNTIME_ROBLOX_APP_LIFECYCLE_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_ROBLOX_BROWSER_SERVICE_BRIDGE_H_
|
||||
#define MOCKTAIL_RUNTIME_ROBLOX_BROWSER_SERVICE_BRIDGE_H_
|
||||
|
||||
@@ -143,11 +129,10 @@ struct RobloxBrowserServiceCallbackFactory {
|
||||
}
|
||||
};
|
||||
|
||||
// equivalent of the current APK's yg.c and gi.a BrowserService bridges.
|
||||
// It binds the four exact MemStorage keys and owns every Callback and
|
||||
// Connection until a disconnect-and-release shutdown has completed. Outgoing
|
||||
// WebView events are queued without JNI and must be drained by the platform
|
||||
// main thread.
|
||||
// Host counterpart to the APK's yg.c and gi.a BrowserService bridges. It binds
|
||||
// the four expected MemStorage keys. Shutdown disconnects before releasing its
|
||||
// callbacks and connections. The platform main thread drains outgoing WebView
|
||||
// events without holding JNI references.
|
||||
class RobloxBrowserServiceBridge final {
|
||||
public:
|
||||
RobloxBrowserServiceBridge(JniEnvironmentProvider environment,
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_ROBLOX_CAPABILITY_RESOLVER_H_
|
||||
#define MOCKTAIL_RUNTIME_ROBLOX_CAPABILITY_RESOLVER_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_ROBLOX_DESKTOP_APP_POLICY_H_
|
||||
#define MOCKTAIL_RUNTIME_ROBLOX_DESKTOP_APP_POLICY_H_
|
||||
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_ROBLOX_EXPERIENCE_COMPOSITION_H_
|
||||
#define MOCKTAIL_RUNTIME_ROBLOX_EXPERIENCE_COMPOSITION_H_
|
||||
|
||||
@@ -21,12 +7,14 @@
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "mocktail/status.h"
|
||||
#include "runtime/owned_pthread.h"
|
||||
#include "runtime/roblox_browser_service_bridge.h"
|
||||
#include "runtime/roblox_experience_launch_bridge.h"
|
||||
#include "runtime/roblox_experience_presence.h"
|
||||
#include "runtime/roblox_fresh_game_launch_controller.h"
|
||||
#include "runtime/roblox_web_view_bridge.h"
|
||||
#include "runtime/webview_roblox_cookie.h"
|
||||
@@ -120,7 +108,9 @@ class RobloxExperienceComposition final {
|
||||
RobloxFreshLaunchPresentBoundary present_boundary,
|
||||
RobloxGameSurfaceJniConfig surface_config = {},
|
||||
const SecureRobloxCredential* initial_web_view_credential = nullptr,
|
||||
RobloxExperienceSurfaceProvider surface_provider = {});
|
||||
RobloxExperienceSurfaceProvider surface_provider = {},
|
||||
RobloxExperiencePresenceObserver presence_observer = {},
|
||||
bool clear_persisted_web_view_cookie = false);
|
||||
~RobloxExperienceComposition();
|
||||
|
||||
RobloxExperienceComposition(const RobloxExperienceComposition&) = delete;
|
||||
@@ -185,6 +175,7 @@ class RobloxExperienceComposition final {
|
||||
void* context, const RobloxBrowserServiceExecuteRequest& request);
|
||||
static void WebSurfaceExited(void* context);
|
||||
static void NotifyLateLuaAppDidReturn(void* context);
|
||||
static void GamePresented(void* context, uint64_t frame_serial);
|
||||
static void* RunLaunchWorker(void* context);
|
||||
static Status RouteWebSurfaceEvent(WebSurfaceRoute route,
|
||||
const WebViewHelperEvent& event,
|
||||
@@ -205,6 +196,7 @@ class RobloxExperienceComposition final {
|
||||
Status Dispatch(const RobloxExperienceLaunchRequest& request);
|
||||
Status PromoteAuthenticatedSession();
|
||||
Status RefreshLateSurface();
|
||||
void PublishPresentedPresence(uint64_t frame_serial);
|
||||
void RunActiveLaunch();
|
||||
Status BuildPlatformGlobalObjects();
|
||||
Status BuildLuaAppGlobalObjects();
|
||||
@@ -218,6 +210,8 @@ class RobloxExperienceComposition final {
|
||||
Status RestartLuaAppSurface(const GameSurface& surface);
|
||||
Status ReleaseLuaAppGlobalObjects();
|
||||
Status ReleaseGlobalObjects();
|
||||
void NotifyPresence(RobloxExperiencePresencePhase phase,
|
||||
const RobloxExperienceLaunchRequest* request) const;
|
||||
|
||||
const JniEnvironmentProvider environment_;
|
||||
const RobloxExperienceMessageBusSymbols message_bus_symbols_;
|
||||
@@ -229,6 +223,7 @@ class RobloxExperienceComposition final {
|
||||
const RobloxGameSurfaceJniConfig surface_config_;
|
||||
const bool consumes_window_surface_events_;
|
||||
const RobloxExperienceSurfaceProvider surface_provider_;
|
||||
const RobloxExperiencePresenceObserver presence_observer_;
|
||||
|
||||
mutable std::mutex mutex_;
|
||||
std::mutex surface_operation_mutex_;
|
||||
@@ -251,8 +246,10 @@ class RobloxExperienceComposition final {
|
||||
SecureWebViewRobloxCookie web_view_cookie_;
|
||||
std::string web_view_cookie_initialization_error_;
|
||||
bool web_view_cookie_synchronized_ = false;
|
||||
bool clear_persisted_web_view_cookie_ = false;
|
||||
std::deque<RobloxExperienceLaunchRequest> pending_launch_requests_;
|
||||
std::unique_ptr<LaunchTask> active_launch_;
|
||||
std::optional<RobloxExperienceLaunchRequest> presence_request_;
|
||||
std::string active_game_canonical_json_;
|
||||
OwnedPthread launch_worker_;
|
||||
uint64_t next_request_id_ = 1;
|
||||
@@ -260,6 +257,7 @@ class RobloxExperienceComposition final {
|
||||
bool subscribed_ = false;
|
||||
bool launch_in_progress_ = false;
|
||||
bool game_active_ = false;
|
||||
bool playing_presence_published_ = false;
|
||||
bool lua_app_return_pending_ = false;
|
||||
bool controlled_switch_waiting_for_return_ = false;
|
||||
bool lua_app_surface_recreation_pending_ = false;
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_ROBLOX_EXPERIENCE_LAUNCH_BRIDGE_H_
|
||||
#define MOCKTAIL_RUNTIME_ROBLOX_EXPERIENCE_LAUNCH_BRIDGE_H_
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef MOCKTAIL_RUNTIME_ROBLOX_EXPERIENCE_PRESENCE_H_
|
||||
#define MOCKTAIL_RUNTIME_ROBLOX_EXPERIENCE_PRESENCE_H_
|
||||
|
||||
#include "runtime/roblox_experience_launch_bridge.h"
|
||||
|
||||
namespace mocktail {
|
||||
namespace runtime {
|
||||
|
||||
enum class RobloxExperiencePresencePhase {
|
||||
kBrowsing,
|
||||
kJoining,
|
||||
kPlaying,
|
||||
};
|
||||
|
||||
using NotifyRobloxExperiencePresenceFn =
|
||||
void (*)(void* context, RobloxExperiencePresencePhase phase,
|
||||
const RobloxExperienceLaunchRequest* request);
|
||||
|
||||
// Non-owning observer retained by RobloxExperienceComposition. Its owner must
|
||||
// outlive the composition. Browsing notifications carry a null request.
|
||||
struct RobloxExperiencePresenceObserver {
|
||||
void* context = nullptr;
|
||||
NotifyRobloxExperiencePresenceFn notify = nullptr;
|
||||
|
||||
bool valid() const { return notify != nullptr; }
|
||||
};
|
||||
|
||||
} // namespace runtime
|
||||
} // namespace mocktail
|
||||
|
||||
#endif // MOCKTAIL_RUNTIME_ROBLOX_EXPERIENCE_PRESENCE_H_
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_ROBLOX_FRESH_GAME_LAUNCH_CONTROLLER_H_
|
||||
#define MOCKTAIL_RUNTIME_ROBLOX_FRESH_GAME_LAUNCH_CONTROLLER_H_
|
||||
|
||||
@@ -86,7 +72,8 @@ class RobloxFreshGameLaunchController final {
|
||||
RobloxFreshGameLaunchController(
|
||||
JniEnvironmentProvider environment, RobloxGameSessionSymbols symbols,
|
||||
RobloxFreshLaunchPresentBoundary present_boundary,
|
||||
RobloxGameSurfaceJniConfig surface_config = {});
|
||||
RobloxGameSurfaceJniConfig surface_config = {},
|
||||
RobloxGamePresentedObserver presented_observer = {});
|
||||
~RobloxFreshGameLaunchController();
|
||||
|
||||
RobloxFreshGameLaunchController(const RobloxFreshGameLaunchController&) =
|
||||
@@ -114,6 +101,7 @@ class RobloxFreshGameLaunchController final {
|
||||
const RobloxGameSessionSymbols symbols_;
|
||||
const RobloxFreshLaunchPresentBoundary present_boundary_;
|
||||
const RobloxGameSurfaceJniConfig surface_config_;
|
||||
const RobloxGamePresentedObserver presented_observer_;
|
||||
|
||||
mutable std::mutex mutex_;
|
||||
std::unique_ptr<RobloxGameSessionRuntime> runtime_;
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2026 Mocktail Project Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MOCKTAIL_RUNTIME_ROBLOX_FULLSCREEN_RUNTIME_BRIDGE_H_
|
||||
#define MOCKTAIL_RUNTIME_ROBLOX_FULLSCREEN_RUNTIME_BRIDGE_H_
|
||||
|
||||
|
||||
Loaded 100 of 445 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user