fix(player): mpv draws all Linux video, and no longer runs text from a URL
Security (DR-298, DR-299): - The pinned libmpv crate's Mpv::command joins its arguments and calls mpv_command_string, which parses `;` as a command separator. Stream URLs carry server-controlled ids and TranscodingUrl, and a download's file:// path carries its track title, so a crafted title could run any mpv command, `run` included. Every call now goes through mpv_command::command, an argv built for mpv_command. The same parse broke loadfile for every downloaded title containing a space. - mpv's tls-verify defaults to no, and its URLs carry the ApiKey. Every handle is now hardened with tls-verify=yes and ytdl=no before its first loadfile, and fails construction if it cannot be. Linux video (DR-235 phase 1): - native_video::enabled() is unconditional on Linux; the JELLYTAU_NATIVE_VIDEO opt-in is retired. No platform reports a webview video fallback, so the Settings switch no longer appears. Windows keeps the webview element until mpv reaches it (DR-237). - The Linux device profile is unchanged (still h264, DR-234), so this ships the configuration that was tested under the env var.
This commit is contained in:
@@ -14,65 +14,50 @@
|
||||
//!
|
||||
//! TRACES: UR-080 | DR-231, DR-235
|
||||
|
||||
/// The opt-in for native desktop video.
|
||||
///
|
||||
/// Off by default while the render path is unproven — the webview path still
|
||||
/// works and is what ships. This becomes the *default* (and then the only path)
|
||||
/// when DR-235 lands; the variable is how it is exercised until then.
|
||||
const ENV_FLAG: &str = "JELLYTAU_NATIVE_VIDEO";
|
||||
|
||||
/// Whether mpv should decode and draw video in this process.
|
||||
///
|
||||
/// Read fresh rather than cached: it is consulted a handful of times at startup,
|
||||
/// and a `OnceLock` here would only make it harder to test.
|
||||
/// True wherever mpv is the desktop video renderer — Linux, since DR-235
|
||||
/// phase 1. There is no opt-out: the webview `<video>` path is no longer a Linux
|
||||
/// video renderer, so "off" would leave nothing drawing the picture. It was the
|
||||
/// `JELLYTAU_NATIVE_VIDEO` opt-in while the render path was being proven; the
|
||||
/// variable is now ignored. Windows joins in DR-237, and only then does the
|
||||
/// webview path go (phase 3).
|
||||
///
|
||||
/// TRACES: UR-080 | DR-231, DR-235
|
||||
pub fn enabled() -> bool {
|
||||
// Only where a native renderer exists. On Android ExoPlayer already does
|
||||
// this and `use_html5_element` is false for entirely separate reasons.
|
||||
if !cfg!(all(target_os = "linux", not(target_os = "android"))) {
|
||||
return false;
|
||||
}
|
||||
matches!(
|
||||
std::env::var(ENV_FLAG).as_deref(),
|
||||
Ok("1") | Ok("true") | Ok("yes")
|
||||
)
|
||||
// On Android ExoPlayer draws video and `use_html5_element` is false for
|
||||
// entirely separate reasons.
|
||||
cfg!(all(target_os = "linux", not(target_os = "android")))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// Absent, empty, or anything unrecognised means off. A half-set variable
|
||||
/// must not half-enable a renderer — the failure mode would be mpv
|
||||
/// configured for video with nothing drawing it, i.e. audio playing over a
|
||||
/// black rectangle.
|
||||
/// mpv draws video on Linux with nothing to opt into, and the retired
|
||||
/// variable cannot opt back out: with the webview path gone from Linux, "off"
|
||||
/// would configure mpv for audio only with nothing else to draw the picture.
|
||||
///
|
||||
/// TRACES: UR-080 | DR-231 | UT-216
|
||||
/// TRACES: UR-080 | DR-235 | UT-271
|
||||
#[test]
|
||||
fn test_only_explicit_truthy_values_enable_it() {
|
||||
let restore = std::env::var(ENV_FLAG).ok();
|
||||
fn linux_always_renders_video_natively() {
|
||||
let restore = std::env::var("JELLYTAU_NATIVE_VIDEO").ok();
|
||||
|
||||
for value in ["", "0", "no", "false", "maybe", "2"] {
|
||||
std::env::set_var(ENV_FLAG, value);
|
||||
assert!(!enabled(), "{value:?} must not enable native video");
|
||||
}
|
||||
|
||||
for value in ["1", "true", "yes"] {
|
||||
std::env::set_var(ENV_FLAG, value);
|
||||
for value in [None, Some("0"), Some("false"), Some("1")] {
|
||||
match value {
|
||||
Some(v) => std::env::set_var("JELLYTAU_NATIVE_VIDEO", v),
|
||||
None => std::env::remove_var("JELLYTAU_NATIVE_VIDEO"),
|
||||
}
|
||||
assert_eq!(
|
||||
enabled(),
|
||||
cfg!(all(target_os = "linux", not(target_os = "android"))),
|
||||
"{value:?} enables it exactly where a native renderer exists"
|
||||
"JELLYTAU_NATIVE_VIDEO={value:?} must not decide the renderer"
|
||||
);
|
||||
}
|
||||
|
||||
std::env::remove_var(ENV_FLAG);
|
||||
assert!(!enabled(), "absent means off");
|
||||
|
||||
match restore {
|
||||
Some(v) => std::env::set_var(ENV_FLAG, v),
|
||||
None => std::env::remove_var(ENV_FLAG),
|
||||
Some(v) => std::env::set_var("JELLYTAU_NATIVE_VIDEO", v),
|
||||
None => std::env::remove_var("JELLYTAU_NATIVE_VIDEO"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user