diff options
| -rw-r--r-- | installer-downloader/src/controller.rs | 21 | ||||
| -rw-r--r-- | mullvad-update/meta/src/platform.rs | 36 | ||||
| -rw-r--r-- | mullvad-update/src/client/api.rs | 56 | ||||
| -rw-r--r-- | mullvad-update/src/defaults.rs | 4 |
4 files changed, 70 insertions, 47 deletions
diff --git a/installer-downloader/src/controller.rs b/installer-downloader/src/controller.rs index f11d93d119..4ad8c44d47 100644 --- a/installer-downloader/src/controller.rs +++ b/installer-downloader/src/controller.rs @@ -9,7 +9,7 @@ use crate::{ }; use mullvad_update::{ - api::{HttpVersionInfoProvider, VersionInfoProvider}, + api::{HttpVersionInfoProvider, MetaRepositoryPlatform, VersionInfoProvider}, app::{self, AppDownloader, HttpAppDownloader}, version::{Version, VersionInfo, VersionParameters}, }; @@ -20,10 +20,6 @@ use tokio::{ task::JoinHandle, }; -/// Base URL for pulling metadata. Actual JSON files should be stored at `<base -/// url>/<platform>.json` -const META_REPOSITORY_URL: &str = "https://api.mullvad.net/app/releases/"; - /// Actions handled by an async worker task in [ActionMessageHandler]. enum TaskMessage { BeginDownload, @@ -46,7 +42,8 @@ pub fn initialize_controller<T: AppDelegate + 'static>(delegate: &mut T, environ // Directory provider to use type DirProvider = crate::temp::TempDirProvider; - let version_provider = HttpVersionInfoProvider::new(get_metadata_url()); + let platform = MetaRepositoryPlatform::current().expect("current platform must be supported"); + let version_provider = HttpVersionInfoProvider::from(platform); AppController::initialize::<_, Downloader<T>, _, DirProvider>( delegate, @@ -55,18 +52,6 @@ pub fn initialize_controller<T: AppDelegate + 'static>(delegate: &mut T, environ ) } -/// JSON files should be stored at `<base url>/<platform>.json`. -fn get_metadata_url() -> String { - const PLATFORM: &str = if cfg!(target_os = "windows") { - "windows" - } else if cfg!(target_os = "macos") { - "macos" - } else { - panic!("Unsupported platform") - }; - format!("{META_REPOSITORY_URL}/{PLATFORM}.json") -} - impl AppController { /// Initialize [AppController] using the provided delegate. /// diff --git a/mullvad-update/meta/src/platform.rs b/mullvad-update/meta/src/platform.rs index ed08915092..0455e5acee 100644 --- a/mullvad-update/meta/src/platform.rs +++ b/mullvad-update/meta/src/platform.rs @@ -2,7 +2,7 @@ use anyhow::{anyhow, bail, Context}; use mullvad_update::{ - api::HttpVersionInfoProvider, + api::{HttpVersionInfoProvider, MetaRepositoryPlatform}, format::{self, key}, }; use std::{ @@ -18,10 +18,6 @@ use crate::{ io_util::{create_dir_and_write, wait_for_confirm}, }; -/// Base URL for metadata found with `meta pull`. -/// Actual JSON files should be stored at `<base url>/<platform>.json`. -const META_REPOSITORY_URL: &str = "https://releases.mullvad.net/desktop/metadata/"; - #[derive(Clone, Copy)] pub enum Platform { Windows, @@ -74,11 +70,6 @@ impl Platform { Path::new("signed").join(self.local_filename()) } - /// URL that stores the latest published metadata - pub fn published_url(&self) -> String { - format!("{META_REPOSITORY_URL}/{}", self.published_filename()) - } - /// Expected artifacts in `artifacts/` directory pub fn artifact_filenames(&self, version: &mullvad_version::Version) -> Artifacts { let artifacts_dir = Path::new("artifacts"); @@ -98,14 +89,6 @@ impl Platform { } } - fn published_filename(&self) -> &str { - match self { - Platform::Windows => "windows.json", - Platform::Linux => "linux.json", - Platform::Macos => "macos.json", - } - } - fn local_filename(&self) -> &str { match self { Platform::Windows => "windows.json", @@ -116,12 +99,11 @@ impl Platform { /// Pull latest metadata from repository and store it in `signed/` pub async fn pull(&self, assume_yes: bool) -> anyhow::Result<()> { - let url = self.published_url(); + let platform = MetaRepositoryPlatform::from(*self); - println!("Pulling {self} metadata from {url}..."); + println!("Pulling {self} metadata from {}...", platform.url()); - let version_provider = HttpVersionInfoProvider::new(url); - let response = version_provider + let response = HttpVersionInfoProvider::from(platform) .get_versions(crate::MIN_VERIFY_METADATA_VERSION) .await .context("Failed to retrieve versions")?; @@ -413,6 +395,16 @@ impl Platform { } } +impl From<Platform> for MetaRepositoryPlatform { + fn from(platform: Platform) -> Self { + match platform { + Platform::Windows => MetaRepositoryPlatform::Windows, + Platform::Linux => MetaRepositoryPlatform::Linux, + Platform::Macos => MetaRepositoryPlatform::Macos, + } + } +} + /// Print release info: /// Version: 2025.3 (arm, x86) (50%) /// <Changelog> diff --git a/mullvad-update/src/client/api.rs b/mullvad-update/src/client/api.rs index c2af2a54c7..a74727b249 100644 --- a/mullvad-update/src/client/api.rs +++ b/mullvad-update/src/client/api.rs @@ -6,6 +6,46 @@ use vec1::Vec1; use crate::format; use crate::version::{VersionInfo, VersionParameters}; +/// Available platforms in the default metadata repository +#[derive(Debug, Clone, Copy)] +pub enum MetaRepositoryPlatform { + Windows, + Linux, + Macos, +} + +impl MetaRepositoryPlatform { + /// Return the current platform + pub fn current() -> Option<Self> { + if cfg!(target_os = "windows") { + Some(Self::Windows) + } else if cfg!(target_os = "linux") { + Some(Self::Linux) + } else if cfg!(target_os = "macos") { + Some(Self::Macos) + } else { + None + } + } + + /// Return complete URL used for the metadata + pub fn url(&self) -> String { + format!( + "{}/{}", + crate::defaults::META_REPOSITORY_URL, + self.filename() + ) + } + + fn filename(&self) -> &str { + match self { + MetaRepositoryPlatform::Windows => "windows.json", + MetaRepositoryPlatform::Linux => "linux.json", + MetaRepositoryPlatform::Macos => "macos.json", + } + } +} + /// See [module-level](self) docs. #[async_trait::async_trait] pub trait VersionInfoProvider { @@ -31,21 +71,23 @@ impl VersionInfoProvider for HttpVersionInfoProvider { } } -impl HttpVersionInfoProvider { - /// Maximum size of the GET response, in bytes - const SIZE_LIMIT: usize = 1024 * 1024; - - /// Construct an [HttpVersionInfoProvider] for `url` using reasonable defaults. +impl From<MetaRepositoryPlatform> for HttpVersionInfoProvider { + /// Construct an [HttpVersionInfoProvider] for the given platform using reasonable defaults. /// /// By default, `pinned_certificate` will be set to the LE root certificate, and /// `verifying_keys` will be set to the keys in `trusted-metadata-signing-keys`. - pub fn new(url: String) -> Self { + fn from(platform: MetaRepositoryPlatform) -> Self { HttpVersionInfoProvider { - url, + url: platform.url(), pinned_certificate: Some(crate::defaults::PINNED_CERTIFICATE.clone()), verifying_keys: crate::defaults::TRUSTED_METADATA_SIGNING_PUBKEYS.clone(), } } +} + +impl HttpVersionInfoProvider { + /// Maximum size of the GET response, in bytes + const SIZE_LIMIT: usize = 1024 * 1024; /// Download and verify signed data pub async fn get_versions( diff --git a/mullvad-update/src/defaults.rs b/mullvad-update/src/defaults.rs index cc58de4bc8..7d6ba5f172 100644 --- a/mullvad-update/src/defaults.rs +++ b/mullvad-update/src/defaults.rs @@ -4,6 +4,10 @@ use crate::format::key::VerifyingKey; use std::sync::LazyLock; use vec1::Vec1; +/// Default repository URL for version metadata +#[cfg(feature = "client")] +pub const META_REPOSITORY_URL: &str = "https://api.mullvad.net/app/releases/"; + /// Default TLS certificate to pin to #[cfg(feature = "client")] pub static PINNED_CERTIFICATE: LazyLock<reqwest::Certificate> = LazyLock::new(|| { |
