Skip to content

Commit

Permalink
Push error handling of get_arch outwards
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkusPettersson98 committed Feb 25, 2025
1 parent d50a3c9 commit 9fd34a6
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 19 deletions.
32 changes: 15 additions & 17 deletions installer-downloader/src/controller.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
//! 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};

use mullvad_update::{
api::VersionInfoProvider,
app::{self, AppDownloader},
version::{Version, VersionArchitecture, VersionInfo, VersionParameters},
version::{Version, VersionInfo, VersionParameters},
};
use rand::seq::SliceRandom;

Expand Down Expand Up @@ -53,7 +54,7 @@ impl VersionInfoProvider for FakeVersionInfoProvider {
}

/// 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
Expand All @@ -73,16 +74,23 @@ pub fn initialize_controller<T: AppDelegate + 'static>(delegate: &mut T) {

let version_provider = FakeVersionInfoProvider {};

AppController::initialize::<_, Downloader<T>, _, DirProvider>(delegate, version_provider)
AppController::initialize::<_, Downloader<T>, _, DirProvider>(
delegate,
version_provider,
environment,
)
}

impl AppController {
/// Initialize [AppController] using the provided delegate.
///
/// 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,
Expand All @@ -106,6 +114,7 @@ impl AppController {
delegate.queue(),
task_tx.clone(),
version_provider,
environment,
));
Self::register_user_action_callbacks(delegate, task_tx);
}
Expand Down Expand Up @@ -138,13 +147,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,
Expand Down Expand Up @@ -425,12 +432,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,
}
}
36 changes: 36 additions & 0 deletions installer-downloader/src/environment.rs
Original file line number Diff line number Diff line change
@@ -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.
// TODO: Attach underlying error
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()
.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)
}
}
2 changes: 2 additions & 0 deletions installer-downloader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 resource;
#[cfg(any(target_os = "windows", target_os = "macos"))]
pub mod temp;
Expand Down
20 changes: 18 additions & 2 deletions installer-downloader/src/winapi_impl/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use native_windows_gui as nwg;
use installer_downloader::environment::{Environment, Error as EnvError};
use native_windows_gui::{self as nwg, modal_fatal_message, ControlHandle};

use crate::delegate::{AppDelegate, AppDelegateQueue};

Expand All @@ -14,9 +15,24 @@ pub fn main() {

let queue = window.borrow().queue();

// Load "global" values and resources
let environment = match Environment::load() {
Ok(env) => env,
Err(error) => show_fatal_error_(error),
};

queue.queue_main(|window| {
crate::controller::initialize_controller(window);
crate::controller::initialize_controller(window, environment);
});

nwg::dispatch_thread_events();
}

fn show_fatal_error_(error: EnvError) -> ! {
let parent = ControlHandle::NoHandle;
let title = "Failed to initialize";
let content = match error {
EnvError::Arch => "Failed to detect CPU architecture",
};
modal_fatal_message(parent, title, content)
}

0 comments on commit 9fd34a6

Please sign in to comment.