use std::{
fs::create_dir_all,
path::{Path, PathBuf},
};
use ureq::ResponseExt;
use crate::utils::http_utils::{base_ureq_agent, download};
pub const WEBVIEW2_BOOTSTRAPPER_URL: &str = "https://go.microsoft.com/fwlink/p/?LinkId=2124703";
pub const WEBVIEW2_OFFLINE_INSTALLER_X86_URL: &str =
"https://go.microsoft.com/fwlink/?linkid=2099617";
pub const WEBVIEW2_OFFLINE_INSTALLER_X64_URL: &str =
"https://go.microsoft.com/fwlink/?linkid=2124701";
pub const WEBVIEW2_URL_PREFIX: &str =
"https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservice/files/";
pub const NSIS_OUTPUT_FOLDER_NAME: &str = "nsis";
pub const NSIS_UPDATER_OUTPUT_FOLDER_NAME: &str = "nsis-updater";
pub const WIX_OUTPUT_FOLDER_NAME: &str = "msi";
pub const WIX_UPDATER_OUTPUT_FOLDER_NAME: &str = "msi-updater";
pub fn webview2_guid_path(url: &str) -> crate::Result<(String, String)> {
let agent = base_ureq_agent();
let response = agent.head(url).call().map_err(Box::new)?;
let final_url = response.get_uri().to_string();
let remaining_url = final_url.strip_prefix(WEBVIEW2_URL_PREFIX).ok_or_else(|| {
crate::Error::GenericError(format!(
"WebView2 URL prefix mismatch. Expected `{WEBVIEW2_URL_PREFIX}`, found `{final_url}`."
))
})?;
let (guid, filename) = remaining_url.split_once('/').ok_or_else(|| {
crate::Error::GenericError(format!(
"WebView2 URL format mismatch. Expected `<GUID>/<FILENAME>`, found `{remaining_url}`."
))
})?;
Ok((guid.into(), filename.into()))
}
pub fn download_webview2_bootstrapper(base_path: &Path) -> crate::Result<PathBuf> {
let file_path = base_path.join("MicrosoftEdgeWebview2Setup.exe");
if !file_path.exists() {
std::fs::write(&file_path, download(WEBVIEW2_BOOTSTRAPPER_URL)?)?;
}
Ok(file_path)
}
pub fn download_webview2_offline_installer(base_path: &Path, arch: &str) -> crate::Result<PathBuf> {
let url = if arch == "x64" {
WEBVIEW2_OFFLINE_INSTALLER_X64_URL
} else {
WEBVIEW2_OFFLINE_INSTALLER_X86_URL
};
let (guid, filename) = webview2_guid_path(url)?;
let dir_path = base_path.join(guid);
let file_path = dir_path.join(filename);
if !file_path.exists() {
create_dir_all(dir_path)?;
std::fs::write(&file_path, download(url)?)?;
}
Ok(file_path)
}
#[cfg(target_os = "windows")]
pub fn processor_architecture<'a>() -> Option<&'a str> {
use windows_sys::Win32::System::SystemInformation::{
GetNativeSystemInfo, PROCESSOR_ARCHITECTURE_AMD64, PROCESSOR_ARCHITECTURE_ARM,
PROCESSOR_ARCHITECTURE_ARM64, PROCESSOR_ARCHITECTURE_INTEL, SYSTEM_INFO,
};
let mut system_info: SYSTEM_INFO = unsafe { std::mem::zeroed() };
unsafe { GetNativeSystemInfo(&mut system_info) };
match unsafe { system_info.Anonymous.Anonymous.wProcessorArchitecture } {
PROCESSOR_ARCHITECTURE_INTEL => Some("x86"),
PROCESSOR_ARCHITECTURE_AMD64 => Some("x64"),
PROCESSOR_ARCHITECTURE_ARM => Some("arm"),
PROCESSOR_ARCHITECTURE_ARM64 => Some("arm64"),
_ => None,
}
}