fix(cef): never forward --time-ticks-at-unix-epoch to CEF (#3554) (#3958)

This commit is contained in:
Mega Mind
2026-06-23 10:26:52 -07:00
committed by GitHub
parent 9c674d91b7
commit 358eeeda6c
2 changed files with 139 additions and 0 deletions
+44
View File
@@ -2012,6 +2012,46 @@ fn append_platform_cef_gpu_workarounds(
}
}
/// Whether a CEF command-line flag is `--time-ticks-at-unix-epoch` (in any
/// dash/casing form, with or without an inline `=<value>` suffix). See
/// [`strip_time_ticks_at_unix_epoch`] for why we care.
fn is_time_ticks_at_unix_epoch_flag(flag: &str) -> bool {
let name = flag.trim_start_matches('-');
// Chromium switches can carry their value inline (`--flag=value`); compare
// only the switch name so the inline form can't slip past the guard.
let name = name.split_once('=').map_or(name, |(n, _)| n);
name.eq_ignore_ascii_case("time-ticks-at-unix-epoch")
}
/// Issue #3554: `--time-ticks-at-unix-epoch` carries the monotonic-clock
/// origin (in microseconds) that CEF child processes — renderer / GPU /
/// utility — use to map Chromium's `TimeTicks` onto wall-clock time. Chromium
/// derives this value itself when it spawns each child, and it must stay
/// consistent with the host clock.
///
/// OpenHuman must never inject this switch into the CEF command line: a stale
/// or negative value (e.g. the `-1780937467390432` reported in #3554) pins the
/// renderer's internal clock ~56 years before the Unix epoch, which surfaces
/// as a wrong "Current Date & Time" in the app. The CEF command line is
/// assembled from several sources (the static list here plus any
/// `RuntimeInitAttribute::CommandLineArgs` contributed elsewhere), so strip the
/// flag from the final list as a guard and let Chromium compute the origin
/// locally for each process.
fn strip_time_ticks_at_unix_epoch(args: &mut Vec<CefCommandLineArg>) {
args.retain(|(flag, value)| {
if is_time_ticks_at_unix_epoch_flag(flag) {
log::warn!(
"[cef-startup] dropping OpenHuman-supplied --time-ticks-at-unix-epoch{} so \
Chromium computes the clock origin locally (issue #3554)",
value.map(|v| format!("={v}")).unwrap_or_default()
);
false
} else {
true
}
});
}
/// Linux only: replace Xlib's default error handler with a logging no-op.
///
/// Why: on Wayland sessions (GNOME/KDE/Hyprland) running CEF via XWayland,
@@ -2653,6 +2693,10 @@ pub fn run() {
std::env::consts::ARCH,
force_gpu_env.as_deref(),
);
// #3554: never forward a `--time-ticks-at-unix-epoch` switch to CEF —
// a corrupt/negative value drives the renderer's clock decades off and
// shows a wrong "Current Date & Time". Let Chromium compute it.
strip_time_ticks_at_unix_epoch(&mut args);
tauri::Builder::<tauri::Cef>::new().command_line_args::<&str, &str>(args)
};
+95
View File
@@ -404,6 +404,101 @@ fn platform_cef_gpu_workarounds_force_gpu_does_not_affect_intel_macos_path() {
assert_eq!(args, vec![("--disable-gpu-compositing", None)]);
}
// -------------------------------------------------------------------------
// #3554 — never forward --time-ticks-at-unix-epoch to CEF (wrong system time)
// -------------------------------------------------------------------------
#[test]
fn time_ticks_flag_matches_any_dash_and_casing_form() {
for flag in [
"--time-ticks-at-unix-epoch",
"-time-ticks-at-unix-epoch",
"time-ticks-at-unix-epoch",
"--Time-Ticks-At-Unix-Epoch",
] {
assert!(
is_time_ticks_at_unix_epoch_flag(flag),
"{flag:?} should be recognised as the time-ticks switch"
);
}
}
#[test]
fn time_ticks_flag_does_not_match_unrelated_flags() {
for flag in [
"--disable-gpu",
"--use-mock-keychain",
"--time-zone",
"--enable-features",
] {
assert!(
!is_time_ticks_at_unix_epoch_flag(flag),
"{flag:?} must not be treated as the time-ticks switch"
);
}
}
#[test]
fn strip_time_ticks_removes_negative_value_and_keeps_the_rest() {
// The corrupt value reported in #3554, alongside flags we must preserve.
let mut args = vec![
("--use-mock-keychain", None),
("--time-ticks-at-unix-epoch", Some("-1780937467390432")),
("--disable-gpu", None),
];
strip_time_ticks_at_unix_epoch(&mut args);
assert_eq!(
args,
vec![("--use-mock-keychain", None), ("--disable-gpu", None)],
"the corrupt time-ticks switch must be removed; everything else kept"
);
}
#[test]
fn strip_time_ticks_removes_inline_value_form() {
// The critical bypass case: when the value is carried inline as
// `--flag=value` (a single token) rather than as a separate value, the
// matcher must still recognise and strip it.
let mut args = vec![
("--use-mock-keychain", None),
("--time-ticks-at-unix-epoch=-1780937467390432", None),
("--disable-gpu", None),
];
strip_time_ticks_at_unix_epoch(&mut args);
assert_eq!(
args,
vec![("--use-mock-keychain", None), ("--disable-gpu", None)],
"the inline time-ticks switch must be removed; everything else kept"
);
}
#[test]
fn strip_time_ticks_removes_the_flag_regardless_of_value() {
// Even a non-negative value is dropped: OpenHuman must let Chromium
// compute the clock origin rather than anchor it from the shell.
let mut args = vec![
("--time-ticks-at-unix-epoch", Some("1780937467390432")),
("--time-ticks-at-unix-epoch", None),
];
strip_time_ticks_at_unix_epoch(&mut args);
assert!(
args.is_empty(),
"all time-ticks variants must be stripped, got: {args:?}"
);
}
#[test]
fn strip_time_ticks_is_a_noop_without_the_flag() {
let mut args = vec![("--use-mock-keychain", None), ("--disable-gpu", None)];
let expected = args.clone();
strip_time_ticks_at_unix_epoch(&mut args);
assert_eq!(args, expected, "unrelated args must be left untouched");
}
/// On an Intel macOS build the ARCH constant must equal "x86_64".
/// This is the architecture that triggers --disable-gpu-compositing.
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]