Skip to content

Commit

Permalink
Add android conditional compilation for google pay
Browse files Browse the repository at this point in the history
Add conditional compilation for google pay API access for only android.
Also allow new error type to be parsed.
Additionally fix review comments, formatting and warnings.
  • Loading branch information
Jontified committed Oct 16, 2023
1 parent a7f9cc0 commit 133d6f1
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 118 deletions.
7 changes: 6 additions & 1 deletion mullvad-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ use chrono::{offset::Utc, DateTime};
use futures::channel::mpsc;
use futures::Stream;
use hyper::Method;
#[cfg(target_os = "android")]
use mullvad_types::account::{PlayPurchase, PlayPurchasePaymentToken};
use mullvad_types::{
account::{AccountToken, PlayPurchase, PlayPurchasePaymentToken, VoucherSubmission},
account::{AccountToken, VoucherSubmission},
version::AppVersion,
};
use proxy::ApiConnectionMode;
Expand Down Expand Up @@ -63,6 +65,7 @@ pub const API_IP_CACHE_FILENAME: &str = "api-ip-address.txt";

const ACCOUNTS_URL_PREFIX: &str = "accounts/v1";
const APP_URL_PREFIX: &str = "app/v1";
#[cfg(target_os = "android")]
const GOOGLE_PAYMENTS_URL_PREFIX: &str = "payments/google-play/v1";

pub static API: LazyManual<ApiEndpoint> = LazyManual::new(ApiEndpoint::from_env_vars);
Expand Down Expand Up @@ -458,6 +461,7 @@ impl AccountsProxy {
}
}

#[cfg(target_os = "android")]
pub fn init_play_purchase(
&mut self,
account_token: AccountToken,
Expand Down Expand Up @@ -490,6 +494,7 @@ impl AccountsProxy {
}
}

#[cfg(target_os = "android")]
pub fn verify_play_purchase(
&mut self,
account_token: AccountToken,
Expand Down
32 changes: 29 additions & 3 deletions mullvad-api/src/rest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,10 +394,17 @@ impl From<Request> for RestRequest {
}

#[derive(serde::Deserialize)]
pub struct ErrorResponse {
struct OldErrorResponse {
pub code: String,
}

/// If `NewErrorResponse::type` is not defined it should default to "about:blank"
const DEFAULT_ERROR_TYPE: &str = "about:blank";
#[derive(serde::Deserialize)]
struct NewErrorResponse {
pub r#type: Option<String>,
}

#[derive(Clone)]
pub struct RequestFactory {
hostname: String,
Expand Down Expand Up @@ -600,8 +607,27 @@ pub async fn handle_error_response<T>(response: Response) -> Result<T> {
status => match get_body_length(&response) {
0 => status.canonical_reason().unwrap_or("Unexpected error"),
body_length => {
let err: ErrorResponse = deserialize_body_inner(response, body_length).await?;
return Err(Error::ApiError(status, err.code));
return match response.headers().get("content-type") {
Some(content_type) if content_type == "application/problem+json" => {
// TODO: We should make sure we unify the new error format and the old
// error format so that they both produce the same Errors for the same
// problems after being processed.
let err: NewErrorResponse =
deserialize_body_inner(response, body_length).await?;
// The new error type replaces the `code` field with the `type` field.
// This is what is used to programmatically check the error.
Err(Error::ApiError(
status,
err.r#type
.unwrap_or_else(|| String::from(DEFAULT_ERROR_TYPE)),
))
}
_ => {
let err: OldErrorResponse =
deserialize_body_inner(response, body_length).await?;
Err(Error::ApiError(status, err.code))
}
};
}
},
};
Expand Down
16 changes: 11 additions & 5 deletions mullvad-daemon/src/device/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ use std::pin::Pin;

use chrono::{DateTime, Utc};
use futures::{future::FusedFuture, Future};
use mullvad_types::{
account::{PlayPurchasePaymentToken, VoucherSubmission},
device::Device,
wireguard::WireguardData,
};
#[cfg(target_os = "android")]
use mullvad_types::account::PlayPurchasePaymentToken;
use mullvad_types::{account::VoucherSubmission, device::Device, wireguard::WireguardData};

use super::{Error, PrivateAccountAndDevice, ResponseTx};

Expand Down Expand Up @@ -51,6 +49,7 @@ impl CurrentApiCall {
self.current_call = Some(Call::VoucherSubmission(voucher_call, Some(tx)));
}

#[cfg(target_os = "android")]
pub fn set_init_play_purchase(
&mut self,
init_play_purchase_call: ApiCall<PlayPurchasePaymentToken>,
Expand All @@ -59,6 +58,7 @@ impl CurrentApiCall {
self.current_call = Some(Call::InitPlayPurchase(init_play_purchase_call, Some(tx)));
}

#[cfg(target_os = "android")]
pub fn set_verify_play_purchase(
&mut self,
verify_play_purchase_call: ApiCall<()>,
Expand Down Expand Up @@ -132,10 +132,12 @@ enum Call {
ApiCall<VoucherSubmission>,
Option<ResponseTx<VoucherSubmission>>,
),
#[cfg(target_os = "android")]
InitPlayPurchase(
ApiCall<PlayPurchasePaymentToken>,
Option<ResponseTx<PlayPurchasePaymentToken>>,
),
#[cfg(target_os = "android")]
VerifyPlayPurchase(ApiCall<()>, Option<ResponseTx<()>>),
ExpiryCheck(ApiCall<DateTime<Utc>>),
}
Expand Down Expand Up @@ -170,6 +172,7 @@ impl futures::Future for Call {
std::task::Poll::Pending
}
}
#[cfg(target_os = "android")]
InitPlayPurchase(call, tx) => {
if let std::task::Poll::Ready(response) = Pin::new(call).poll(cx) {
std::task::Poll::Ready(ApiResult::InitPlayPurchase(
Expand All @@ -180,6 +183,7 @@ impl futures::Future for Call {
std::task::Poll::Pending
}
}
#[cfg(target_os = "android")]
VerifyPlayPurchase(call, tx) => {
if let std::task::Poll::Ready(response) = Pin::new(call).poll(cx) {
std::task::Poll::Ready(ApiResult::VerifyPlayPurchase(
Expand All @@ -203,10 +207,12 @@ pub(crate) enum ApiResult {
Result<VoucherSubmission, Error>,
ResponseTx<VoucherSubmission>,
),
#[cfg(target_os = "android")]
InitPlayPurchase(
Result<PlayPurchasePaymentToken, Error>,
ResponseTx<PlayPurchasePaymentToken>,
),
#[cfg(target_os = "android")]
VerifyPlayPurchase(Result<(), Error>, ResponseTx<()>),
ExpiryCheck(Result<DateTime<Utc>, Error>),
}
Loading

0 comments on commit 133d6f1

Please sign in to comment.