build: bundle playback and YouTube dependencies
Build pinned LGPL playback libraries and package standalone YouTube helpers inside the signed native app. Keep the CLI inside the app and relocate private library links for installation without runtime Homebrew dependencies. Record adaptive fixture completion in its EXIT trap: cancellation can exit with status 143 before the TERM trap writes its marker, while native pause and quality preservation remain correct.
This commit is contained in:
Executable
+96
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Exercise relocated runtime payloads with Homebrew and original build inputs denied."""
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
|
||||
PROBE = r'''
|
||||
import ctypes
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
app, movie = map(Path, sys.argv[1:])
|
||||
frameworks = app / "Contents/Frameworks"
|
||||
names = (app / "Contents/Resources/ffmpeg-libraries.txt").read_text().splitlines()
|
||||
libraries = {name.split(".")[0]: ctypes.CDLL(str(frameworks / name)) for name in names}
|
||||
format = libraries["libavformat"]
|
||||
codec = libraries["libavcodec"]
|
||||
codec.avcodec_license.restype = ctypes.c_char_p
|
||||
assert codec.avcodec_license() == b"LGPL version 2.1 or later", codec.avcodec_license()
|
||||
codec.avcodec_find_decoder_by_name.argtypes = [ctypes.c_char_p]
|
||||
codec.avcodec_find_decoder_by_name.restype = ctypes.c_void_p
|
||||
assert codec.avcodec_find_decoder_by_name(b"libdav1d"), "software AV1 decoder absent"
|
||||
context = ctypes.c_void_p()
|
||||
format.avformat_open_input.argtypes = [ctypes.POINTER(ctypes.c_void_p), ctypes.c_char_p, ctypes.c_void_p, ctypes.c_void_p]
|
||||
format.avformat_find_stream_info.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
|
||||
format.avformat_close_input.argtypes = [ctypes.POINTER(ctypes.c_void_p)]
|
||||
assert format.avformat_open_input(ctypes.byref(context), bytes(movie), None, None) == 0
|
||||
try:
|
||||
assert format.avformat_find_stream_info(context, None) >= 0
|
||||
finally:
|
||||
format.avformat_close_input(ctypes.byref(context))
|
||||
print(json.dumps({"media_read": True, "software_av1": True, "license": codec.avcodec_license().decode()}))
|
||||
'''
|
||||
|
||||
|
||||
def main():
|
||||
source, fixtures, dependency_root = map(lambda value: Path(value).resolve(), sys.argv[1:])
|
||||
with tempfile.TemporaryDirectory(prefix="terebi-bundle-") as directory:
|
||||
root = Path(directory)
|
||||
app = root / "relocated player.app"
|
||||
shutil.copytree(source, app)
|
||||
movie = root / "media with spaces.mp4"
|
||||
shutil.copy2(fixtures / "av.mp4", movie)
|
||||
macOS = app / "Contents/MacOS"
|
||||
cli = root / "terebi"
|
||||
cli.symlink_to(macOS / "terebi-cli")
|
||||
profile = '(version 1)(allow default)' + ''.join(
|
||||
'(deny file-read* (subpath ' + json.dumps(str(path)) + '))'
|
||||
for path in (Path("/opt/homebrew"), Path("/usr/local"), source, dependency_root))
|
||||
environment = {key: value for key, value in os.environ.items()
|
||||
if not key.startswith(("DYLD_", "PYTHON"))}
|
||||
environment.update(PATH="/usr/bin:/bin", XDG_CONFIG_HOME=str(root / "xdg"), PYTHONNOUSERSITE="1")
|
||||
|
||||
def invoke(arguments, expected=0):
|
||||
result = subprocess.run(["/usr/bin/sandbox-exec", "-p", profile, *map(str, arguments)],
|
||||
env=environment, capture_output=True, text=True, timeout=45)
|
||||
if result.returncode != expected:
|
||||
raise RuntimeError(f"Relocated command {arguments} returned {result.returncode}, expected {expected}:\n{result.stdout}{result.stderr}")
|
||||
return result
|
||||
|
||||
invoke([cli, "--help"])
|
||||
invoke([cli, "--default-config"])
|
||||
native = invoke(["/usr/bin/python3", "-c", PROBE, app, movie])
|
||||
print("PASS relocated private codec libraries:", native.stdout.strip())
|
||||
deno = invoke([macOS / "deno", "eval", "--no-config", "--no-remote", "--no-npm",
|
||||
'console.log(JSON.stringify([1,2,3].map(n => n * n)))'])
|
||||
assert json.loads(deno.stdout) == [1, 4, 9], "bundled JavaScript runtime did not execute"
|
||||
metadata = root / "youtube.json"
|
||||
metadata.write_text(json.dumps({
|
||||
"id": "jNQXAC9IVRw", "title": "Offline bundle fixture", "duration": 4,
|
||||
"webpage_url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
|
||||
"extractor": "youtube", "extractor_key": "Youtube", "formats": [{
|
||||
"format_id": "360", "height": 360, "width": 640, "ext": "mp4",
|
||||
"url": "https://media.example/fixture.mp4", "protocol": "https", "vcodec": "h264", "acodec": "aac"}]}))
|
||||
extracted = invoke([macOS / "yt-dlp", "--ignore-config", "--no-plugin-dirs", "--no-cache-dir",
|
||||
"--no-remote-components", "--no-js-runtimes", "--js-runtimes", "deno:" + str(macOS / "deno"),
|
||||
"--verbose", "--simulate", "--skip-download", "--dump-single-json", "--no-check-formats",
|
||||
"--load-info-json", metadata])
|
||||
video = json.loads(extracted.stdout)
|
||||
assert video["url"] == "https://media.example/fixture.mp4" and video["height"] == 360
|
||||
assert "yt_dlp_ejs" in extracted.stderr and "deno-" in extracted.stderr, extracted.stderr
|
||||
print("PASS relocated standalone yt-dlp, packaged Python/EJS and Deno without host tools")
|
||||
missing = next((app / "Contents/Frameworks").glob("libdav1d.*.dylib"))
|
||||
missing.rename(root / "removed-dav1d.dylib")
|
||||
failure = invoke([cli, "--new-instance", "--no-config"], expected=69)
|
||||
print("PASS missing bundled transitive library blocks launch:", failure.stderr.strip())
|
||||
invoke([cli, "--help"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user