use url::Url;
use crate::config::{ProxyConfig, ProxyConfigSource};
use crate::error::Error;
use crate::mode::ProxyMode;
use crate::resolve::ProxyStep;
#[derive(Debug, Clone, Default)]
pub struct AndroidPacResolver {
_private: (),
}
impl AndroidPacResolver {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn resolve_config(&self, config: &ProxyConfig, url: &Url) -> Result<Vec<ProxyStep>, Error> {
let mode = &config.effective;
match mode {
ProxyMode::Pac { .. } | ProxyMode::PacInline { .. } | ProxyMode::WpadAutoDetect
if !crate::endpoint::has_request_host(url) =>
{
Ok(vec![ProxyStep::Direct])
}
ProxyMode::Pac { url: pac_url, .. }
if config.source(ProxyConfigSource::ConnectivityManager) == Some(mode) =>
{
resolve(url, pac_url)
}
_ => crate::resolve::resolve(config, url),
}
}
}
fn resolve(url: &Url, pac_url: &Url) -> Result<Vec<ProxyStep>, Error> {
let target = crate::pac::sanitize_url(url);
let (live, selected) =
crate::sys::android::select(&crate::sys::proxy_info::java_uri_text(&target))?;
let live = live.and_then(|live| Url::parse(&live).ok());
if live.as_ref() != Some(pac_url) {
return Err(Error::io(
"resolving PAC through ProxySelector",
std::io::Error::other("the system proxy settings no longer name this PAC script"),
));
}
let Some(selected) = selected else {
return Err(Error::io(
"resolving PAC through ProxySelector",
std::io::Error::other(
"the default ProxySelector is not the system's PacProxySelector: the process \
has not installed it yet, or the app replaced it",
),
));
};
crate::sys::proxy_info::steps_from_selected(&selected)
}