diff --git a/src-tauri/src/core/sysopt.rs b/src-tauri/src/core/sysopt.rs index 163c7adca..6070caae5 100644 --- a/src-tauri/src/core/sysopt.rs +++ b/src-tauri/src/core/sysopt.rs @@ -17,6 +17,22 @@ use std::{ use sysproxy::{Autoproxy, GuardMonitor, GuardType, Sysproxy}; use tokio::sync::Mutex as TokioMutex; +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum ProxyApplyStep { + Sysproxy, + Autoproxy, +} + +const fn proxy_apply_steps(sys_enabled: bool, auto_enabled: bool) -> [ProxyApplyStep; 2] { + // Disabling PAC clears WinINET proxy flags on Windows, so pure global + // proxy mode must clear PAC before enabling Sysproxy. + if sys_enabled && !auto_enabled { + [ProxyApplyStep::Autoproxy, ProxyApplyStep::Sysproxy] + } else { + [ProxyApplyStep::Sysproxy, ProxyApplyStep::Autoproxy] + } +} + pub struct Sysopt { update_lock: TokioMutex<()>, reset_sysproxy: AtomicBool, @@ -169,9 +185,15 @@ impl Sysopt { self.access_guard().write().set_guard_type(guard_type); + let apply_steps = proxy_apply_steps(sys.enable, auto.enable); + tokio::task::spawn_blocking(move || -> Result<()> { - sys.set_system_proxy()?; - auto.set_auto_proxy()?; + for step in apply_steps { + match step { + ProxyApplyStep::Autoproxy => auto.set_auto_proxy()?, + ProxyApplyStep::Sysproxy => sys.set_system_proxy()?, + } + } Ok(()) }) .await??; @@ -213,3 +235,32 @@ impl Sysopt { Ok(()) } } + +#[cfg(test)] +mod tests { + use super::{ProxyApplyStep, proxy_apply_steps}; + + #[test] + fn pure_sysproxy_mode_clears_pac_before_enabling_global_proxy() { + assert_eq!( + proxy_apply_steps(true, false), + [ProxyApplyStep::Autoproxy, ProxyApplyStep::Sysproxy] + ); + } + + #[test] + fn pac_mode_clears_global_proxy_before_enabling_pac() { + assert_eq!( + proxy_apply_steps(false, true), + [ProxyApplyStep::Sysproxy, ProxyApplyStep::Autoproxy] + ); + } + + #[test] + fn disabled_mode_clears_global_proxy_before_pac() { + assert_eq!( + proxy_apply_steps(false, false), + [ProxyApplyStep::Sysproxy, ProxyApplyStep::Autoproxy] + ); + } +}