Source code

Revision control

Copy as Markdown

Other Tools

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
use std::collections::HashMap;
use client::error::ComponentError;
use error_support::handle_error;
use mars::error::CallbackRequestError;
use parking_lot::Mutex;
use url::Url as AdsClientUrl;
use client::AdsClient;
use http_cache::CachePolicy;
use mars::ad_request::AdPlacementRequest;
mod client;
mod ffi;
pub mod http_cache;
mod mars;
pub mod telemetry;
pub use ffi::*;
use crate::ffi::telemetry::MozAdsTelemetryWrapper;
#[cfg(test)]
mod test_utils;
uniffi::setup_scaffolding!("ads_client");
uniffi::custom_type!(AdsClientUrl, String, {
remote,
try_lift: |val| Ok(AdsClientUrl::parse(&val)?),
lower: |obj| obj.as_str().to_string(),
});
#[derive(uniffi::Object)]
pub struct MozAdsClient {
inner: Mutex<AdsClient<MozAdsTelemetryWrapper>>,
}
#[uniffi::export]
impl MozAdsClient {
pub fn clear_cache(&self) -> AdsClientApiResult<()> {
let inner = self.inner.lock();
inner
.clear_cache()
.map_err(|e| MozAdsClientApiError::Other {
reason: format!("Failed to clear cache: {}", e),
})
}
#[handle_error(ComponentError)]
#[uniffi::method(default(options = None))]
pub fn record_click(
&self,
click_url: String,
options: Option<MozAdsCallbackOptions>,
) -> AdsClientApiResult<()> {
let url = AdsClientUrl::parse(&click_url)
.map_err(|e| ComponentError::RecordClick(CallbackRequestError::InvalidUrl(e).into()))?;
let ohttp = options.map(|o| o.ohttp).unwrap_or(false);
let inner = self.inner.lock();
inner
.record_click(url, ohttp)
.map_err(ComponentError::RecordClick)
}
#[handle_error(ComponentError)]
#[uniffi::method(default(options = None))]
pub fn record_impression(
&self,
impression_url: String,
options: Option<MozAdsCallbackOptions>,
) -> AdsClientApiResult<()> {
let url = AdsClientUrl::parse(&impression_url).map_err(|e| {
ComponentError::RecordImpression(CallbackRequestError::InvalidUrl(e).into())
})?;
let ohttp = options.map(|o| o.ohttp).unwrap_or(false);
let inner = self.inner.lock();
inner
.record_impression(url, ohttp)
.map_err(ComponentError::RecordImpression)
}
#[handle_error(ComponentError)]
#[uniffi::method(default(options = None))]
pub fn report_ad(
&self,
report_url: String,
reason: MozAdsReportReason,
options: Option<MozAdsCallbackOptions>,
) -> AdsClientApiResult<()> {
let url = AdsClientUrl::parse(&report_url)
.map_err(|e| ComponentError::ReportAd(CallbackRequestError::InvalidUrl(e).into()))?;
let ohttp = options.map(|o| o.ohttp).unwrap_or(false);
let inner = self.inner.lock();
inner
.report_ad(url, reason.into(), ohttp)
.map_err(ComponentError::ReportAd)
}
#[handle_error(ComponentError)]
#[uniffi::method(default(options = None))]
pub fn request_image_ads(
&self,
moz_ad_requests: Vec<MozAdsPlacementRequest>,
options: Option<MozAdsRequestOptions>,
) -> AdsClientApiResult<HashMap<String, MozAdsImage>> {
let inner = self.inner.lock();
let requests: Vec<AdPlacementRequest> = moz_ad_requests.iter().map(|r| r.into()).collect();
let ohttp = options.as_ref().map(|o| o.ohttp).unwrap_or(false);
let cache_policy: CachePolicy = options.into();
let response = inner
.request_image_ads(requests, Some(cache_policy), ohttp)
.map_err(ComponentError::RequestAds)?;
Ok(response.into_iter().map(|(k, v)| (k, v.into())).collect())
}
#[handle_error(ComponentError)]
#[uniffi::method(default(options = None))]
pub fn request_spoc_ads(
&self,
moz_ad_requests: Vec<MozAdsPlacementRequestWithCount>,
options: Option<MozAdsRequestOptions>,
) -> AdsClientApiResult<HashMap<String, Vec<MozAdsSpoc>>> {
let inner = self.inner.lock();
let requests: Vec<AdPlacementRequest> = moz_ad_requests.iter().map(|r| r.into()).collect();
let ohttp = options.as_ref().map(|o| o.ohttp).unwrap_or(false);
let cache_policy: CachePolicy = options.into();
let response = inner
.request_spoc_ads(requests, Some(cache_policy), ohttp)
.map_err(ComponentError::RequestAds)?;
Ok(response
.into_iter()
.map(|(k, v)| (k, v.into_iter().map(|spoc| spoc.into()).collect()))
.collect())
}
#[handle_error(ComponentError)]
#[uniffi::method(default(options = None))]
pub fn request_tile_ads(
&self,
moz_ad_requests: Vec<MozAdsPlacementRequest>,
options: Option<MozAdsRequestOptions>,
) -> AdsClientApiResult<HashMap<String, MozAdsTile>> {
let inner = self.inner.lock();
let requests: Vec<AdPlacementRequest> = moz_ad_requests.iter().map(|r| r.into()).collect();
let ohttp = options.as_ref().map(|o| o.ohttp).unwrap_or(false);
let cache_policy: CachePolicy = options.into();
let response = inner
.request_tile_ads(requests, Some(cache_policy), ohttp)
.map_err(ComponentError::RequestAds)?;
Ok(response.into_iter().map(|(k, v)| (k, v.into())).collect())
}
}