use std::path::Path;
use crate::error::AppError;
const EXTENSION_ID: &str = "gdpr@cavi.au.dk";
const XPI_URL: &str =
"https://addons.mozilla.org/firefox/downloads/file/4515369/consent_o_matic-1.1.5.xpi";
fn cached_xpi_path() -> Result<std::path::PathBuf, AppError> {
let base = dirs::cache_dir().ok_or_else(|| {
AppError::User("cannot determine cache directory for extension download".to_owned())
})?;
Ok(base
.join("ff-rdp")
.join("extensions")
.join(format!("{EXTENSION_ID}.xpi")))
}
fn ensure_cached() -> Result<std::path::PathBuf, AppError> {
let path = cached_xpi_path()?;
if path.is_file() {
return Ok(path);
}
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent).map_err(|e| {
AppError::User(format!(
"failed to create cache directory {}: {e}",
parent.display()
))
})?;
}
let agent = ureq::Agent::new_with_config(
ureq::config::Config::builder()
.timeout_connect(Some(std::time::Duration::from_secs(10)))
.timeout_recv_body(Some(std::time::Duration::from_secs(30)))
.build(),
);
let response = agent.get(XPI_URL).call().map_err(|e| {
AppError::User(format!("failed to download Consent-O-Matic extension: {e}"))
})?;
let body = response
.into_body()
.read_to_vec()
.map_err(|e| AppError::User(format!("failed to read extension download: {e}")))?;
let tmp_path = path.with_extension(format!("xpi.tmp.{}", std::process::id()));
std::fs::write(&tmp_path, &body)
.map_err(|e| AppError::User(format!("failed to write cached extension: {e}")))?;
std::fs::rename(&tmp_path, &path)
.map_err(|e| AppError::User(format!("failed to finalize cached extension: {e}")))?;
Ok(path)
}
pub(crate) fn install(profile_dir: &Path) -> Result<(), AppError> {
let cached = ensure_cached()?;
let ext_dir = profile_dir.join("extensions");
std::fs::create_dir_all(&ext_dir).map_err(|e| {
AppError::User(format!(
"failed to create extensions directory {}: {e}",
ext_dir.display()
))
})?;
let dest = ext_dir.join(format!("{EXTENSION_ID}.xpi"));
std::fs::copy(&cached, &dest).map_err(|e| {
AppError::User(format!(
"failed to install Consent-O-Matic to {}: {e}",
dest.display()
))
})?;
Ok(())
}