summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarkus Pettersson <markus.pettersson@mullvad.net>2025-02-24 10:22:34 +0100
committerDavid Lönnhager <david.l@mullvad.net>2025-03-05 23:32:30 +0100
commit5605ba9037597aeb8577c8a068e19ca1854bb997 (patch)
treef742ae88b25f423d16bf8496527e4ef6e8634cec
parentaefca5230e86aaf03fc3b1daa1c72f90f32fb693 (diff)
downloadmullvadvpn-5605ba9037597aeb8577c8a068e19ca1854bb997.tar.xz
mullvadvpn-5605ba9037597aeb8577c8a068e19ca1854bb997.zip
Push error handling of `get_arch` outwards
-rw-r--r--installer-downloader/src/cacao_impl/mod.rs11
-rw-r--r--installer-downloader/src/controller.rs32
-rw-r--r--installer-downloader/src/environment.rs36
-rw-r--r--installer-downloader/src/lib.rs2
-rw-r--r--installer-downloader/src/winapi_impl/mod.rs16
5 files changed, 78 insertions, 19 deletions
diff --git a/installer-downloader/src/cacao_impl/mod.rs b/installer-downloader/src/cacao_impl/mod.rs
index e2974d370e..3b607c3295 100644
--- a/installer-downloader/src/cacao_impl/mod.rs
+++ b/installer-downloader/src/cacao_impl/mod.rs
@@ -1,6 +1,7 @@
use std::sync::Mutex;
use cacao::appkit::App;
+use installer_downloader::environment::{Environment, Error as EnvError};
use ui::{Action, AppImpl};
mod delegate;
@@ -9,8 +10,16 @@ mod ui;
pub fn main() {
let app = App::new("net.mullvad.downloader", AppImpl::default());
+ // Load "global" values and resources
+ let environment = match Environment::load() {
+ Ok(env) => env,
+ Err(EnvError::Arch) => {
+ unreachable!("The CPU architecture will always be retrievable on macOS")
+ }
+ };
+
let cb: Mutex<Option<ui::MainThreadCallback>> = Mutex::new(Some(Box::new(|self_| {
- crate::controller::initialize_controller(self_);
+ crate::controller::initialize_controller(self_, environment);
})));
cacao::appkit::App::<ui::AppImpl, _>::dispatch_main(Action::QueueMain(cb));
diff --git a/installer-downloader/src/controller.rs b/installer-downloader/src/controller.rs
index ff02b3cd0c..ebed872755 100644
--- a/installer-downloader/src/controller.rs
+++ b/installer-downloader/src/controller.rs
@@ -1,6 +1,7 @@
//! This module implements the actual logic performed by different UI components.
use crate::delegate::{AppDelegate, AppDelegateQueue};
+use crate::environment::Environment;
use crate::resource;
use crate::temp::DirectoryProvider;
use crate::ui_downloader::{UiAppDownloader, UiAppDownloaderParameters, UiProgressUpdater};
@@ -8,7 +9,7 @@ use crate::ui_downloader::{UiAppDownloader, UiAppDownloaderParameters, UiProgres
use mullvad_update::{
api::VersionInfoProvider,
app::{self, AppDownloader},
- version::{Version, VersionArchitecture, VersionInfo, VersionParameters},
+ version::{Version, VersionInfo, VersionParameters},
};
use rand::seq::SliceRandom;
@@ -29,7 +30,7 @@ enum TaskMessage {
pub struct AppController {}
/// Public entry function for registering a [AppDelegate].
-pub fn initialize_controller<T: AppDelegate + 'static>(delegate: &mut T) {
+pub fn initialize_controller<T: AppDelegate + 'static>(delegate: &mut T, environment: Environment) {
use mullvad_update::{api::HttpVersionInfoProvider, app::HttpAppDownloader};
// App downloader to use
@@ -48,7 +49,11 @@ pub fn initialize_controller<T: AppDelegate + 'static>(delegate: &mut T) {
verifying_key,
};
- AppController::initialize::<_, Downloader<T>, _, DirProvider>(delegate, version_provider)
+ AppController::initialize::<_, Downloader<T>, _, DirProvider>(
+ delegate,
+ version_provider,
+ environment,
+ )
}
/// JSON files should be stored at `<base url>/<platform>.json`.
@@ -68,8 +73,11 @@ impl AppController {
///
/// Providing the downloader and version info fetcher as type arguments, they're decoupled from
/// the logic of [AppController], allowing them to be mocked.
- pub fn initialize<D, A, V, DirProvider>(delegate: &mut D, version_provider: V)
- where
+ pub fn initialize<D, A, V, DirProvider>(
+ delegate: &mut D,
+ version_provider: V,
+ environment: Environment,
+ ) where
D: AppDelegate + 'static,
V: VersionInfoProvider + Send + 'static,
A: From<UiAppDownloaderParameters<D>> + AppDownloader + 'static,
@@ -93,6 +101,7 @@ impl AppController {
delegate.queue(),
task_tx.clone(),
version_provider,
+ environment,
));
Self::register_user_action_callbacks(delegate, task_tx);
}
@@ -125,13 +134,11 @@ async fn fetch_app_version_info<Delegate, VersionProvider>(
queue: Delegate::Queue,
download_tx: mpsc::Sender<TaskMessage>,
version_provider: VersionProvider,
+ Environment { architecture }: Environment,
) where
Delegate: AppDelegate + 'static,
VersionProvider: VersionInfoProvider + Send,
{
- // TODO: Do not unwrap
- // TODO: Construct a proper error instead
- let architecture = get_arch().unwrap().unwrap();
loop {
let version_params = VersionParameters {
architecture,
@@ -412,12 +419,3 @@ fn select_cdn_url(urls: &[String]) -> Option<&str> {
fn format_latest_version(version: &Version) -> String {
format!("{}: {}", resource::LATEST_VERSION_PREFIX, version.version)
}
-
-/// Try to map the host's CPU architecture to one of the CPU architectures the Mullvad VPN app
-/// supports.
-fn get_arch() -> Result<Option<VersionArchitecture>, std::io::Error> {
- match talpid_platform_metadata::get_native_arch()?? {
- talpid_platform_metadata::Architecture::X86 => VersionArchitecture::X86,
- talpid_platform_metadata::Architecture::Arm64 => VersionArchitecture::Arm64,
- }
-}
diff --git a/installer-downloader/src/environment.rs b/installer-downloader/src/environment.rs
new file mode 100644
index 0000000000..4b17575912
--- /dev/null
+++ b/installer-downloader/src/environment.rs
@@ -0,0 +1,36 @@
+use mullvad_update::version::VersionArchitecture;
+
+/// The environment consists of globals and/or constants which need to be computed at runtime.
+pub struct Environment {
+ pub architecture: mullvad_update::format::Architecture,
+}
+
+pub enum Error {
+ /// Failed to get the host's CPU architecture.
+ Arch,
+}
+
+impl Environment {
+ /// Try to load the environment.
+ pub fn load() -> Result<Self, Error> {
+ let architecture = Self::get_arch()?;
+
+ Ok(Environment { architecture })
+ }
+
+ /// Try to map the host's CPU architecture to one of the CPU architectures the Mullvad VPN app
+ /// supports.
+ fn get_arch() -> Result<VersionArchitecture, Error> {
+ let arch = talpid_platform_metadata::get_native_arch()
+ .inspect_err(|err| log::debug!("{err}"))
+ .map_err(|_| Error::Arch)?
+ .ok_or(Error::Arch)?;
+
+ let arch = match arch {
+ talpid_platform_metadata::Architecture::X86 => VersionArchitecture::X86,
+ talpid_platform_metadata::Architecture::Arm64 => VersionArchitecture::Arm64,
+ };
+
+ Ok(arch)
+ }
+}
diff --git a/installer-downloader/src/lib.rs b/installer-downloader/src/lib.rs
index bde7683cdc..a07d557d67 100644
--- a/installer-downloader/src/lib.rs
+++ b/installer-downloader/src/lib.rs
@@ -3,6 +3,8 @@ pub mod controller;
#[cfg(any(target_os = "windows", target_os = "macos"))]
pub mod delegate;
#[cfg(any(target_os = "windows", target_os = "macos"))]
+pub mod environment;
+#[cfg(any(target_os = "windows", target_os = "macos"))]
pub mod log;
#[cfg(any(target_os = "windows", target_os = "macos"))]
pub mod resource;
diff --git a/installer-downloader/src/winapi_impl/mod.rs b/installer-downloader/src/winapi_impl/mod.rs
index 15a9957c00..fe755009da 100644
--- a/installer-downloader/src/winapi_impl/mod.rs
+++ b/installer-downloader/src/winapi_impl/mod.rs
@@ -1,3 +1,4 @@
+use installer_downloader::environment::{Environment, Error as EnvError};
use native_windows_gui as nwg;
use crate::delegate::{AppDelegate, AppDelegateQueue};
@@ -9,14 +10,27 @@ pub fn main() {
nwg::init().expect("Failed to init Native Windows GUI");
nwg::Font::set_global_family("Segoe UI").expect("Failed to set default font");
+ // Load "global" values and resources
+ let environment = match Environment::load() {
+ Ok(env) => env,
+ Err(error) => fatal_environment_error(error),
+ };
+
let window = ui::AppWindow::default();
let window = window.layout().unwrap();
let queue = window.borrow().queue();
queue.queue_main(|window| {
- crate::controller::initialize_controller(window);
+ crate::controller::initialize_controller(window, environment);
});
nwg::dispatch_thread_events();
}
+
+fn fatal_environment_error(error: EnvError) -> ! {
+ let content = match error {
+ EnvError::Arch => "Failed to detect CPU architecture",
+ };
+ nwg::fatal_message(installer_downloader::resource::WINDOW_TITLE, content)
+}