fix: handling failures/invalid popup edge cases to show normal gdpr popup fallback (#6857)

* fix: remove drilling actions down iframes

* refactor: split up custom popup logic, trim it down a lot

* fix: bring back TCF useractioncomplete and USP/GPP sectionChange event listeners, and only using dom observer as the fallback

* remove open devtools

* format

* harden CPM fallbacks for unknown layouts

* consolidate timeouts

* refactor: rename functions to make sense

* fix: sidebar closed on launch does not properly set state
This commit is contained in:
Truman Gao
2026-07-24 16:48:52 +00:00
committed by GitHub
parent fbe70c6938
commit dfc2ed3783
12 changed files with 1128 additions and 1041 deletions
+58 -65
View File
@@ -12,6 +12,7 @@ pub struct AdsState {
pub shown: bool,
pub modal_shown: bool,
pub consent_required: bool,
pub consent_notification_enabled: bool,
pub consent_overlay_shown: bool,
pub occluded: bool,
pub last_click: Option<Instant>,
@@ -278,6 +279,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
shown: true,
modal_shown: false,
consent_required: false,
consent_notification_enabled: false,
consent_overlay_shown: false,
occluded: false,
last_click: None,
@@ -361,12 +363,11 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
init_ads_window,
hide_ads_window,
show_ads_window,
show_ads_consent_overlay,
show_ads_consent_preferences,
show_ads_consent_ui,
expand_ads_consent_webview,
open_ads_consent_preferences,
hide_ads_consent_preferences,
hide_ads_consent_overlay,
get_ads_consent_required,
finish_ads_consent_flow,
should_show_ads_consent_popup,
perform_ads_consent_action,
record_ads_click,
open_link,
@@ -475,6 +476,19 @@ pub async fn init_ads_window<R: Runtime>(
Some(webview.clone())
} else if let Some(window) = app.get_window("main") {
let ads_consent_script = [
"(() => {",
include_str!("ads-consent/state.js"),
include_str!("ads-consent/styles.js"),
include_str!("ads-consent/bridge.js"),
include_str!("ads-consent/cmp.js"),
include_str!("ads-consent/media.js"),
include_str!("ads-consent/controller.js"),
include_str!("ads-consent/index.js"),
"})()",
]
.join("\n");
#[cfg(windows)]
let webview_url =
WebviewUrl::External("about:blank".parse().unwrap());
@@ -483,9 +497,7 @@ pub async fn init_ads_window<R: Runtime>(
let webview = window.add_child(
tauri::webview::WebviewBuilder::new("ads-window", webview_url)
.initialization_script_for_all_frames(include_str!(
"ads-init.js"
))
.initialization_script_for_all_frames(ads_consent_script)
// We use a standard Chrome user agent for compatibility with our ad provider,
// since Tauri is not recognized by ad providers by default.
// Aditude has separately informed SSPs and IVT vendors that this traffic
@@ -644,7 +656,10 @@ pub async fn init_ads_window<R: Runtime>(
// });
}
if state.shown && state.consent_required {
if state.shown
&& state.consent_required
&& state.consent_notification_enabled
{
app.emit_to("main", ADS_CONSENT_REQUIRED_EVENT, true).ok();
}
@@ -661,7 +676,7 @@ pub async fn show_ads_window<R: Runtime>(
app: tauri::AppHandle<R>,
dpr: f32,
) -> crate::api::Result<()> {
let mut consent_required = false;
let mut show_consent_notification = false;
if let Some(webview) = app.webviews().get("ads-window") {
let state = app.state::<RwLock<AdsState>>();
@@ -683,10 +698,12 @@ pub async fn show_ads_window<R: Runtime>(
set_webview_visible_for_window(&app, webview, true);
}
consent_required = state.shown && state.consent_required;
show_consent_notification = state.shown
&& state.consent_required
&& state.consent_notification_enabled;
}
if consent_required {
if show_consent_notification {
app.emit_to("main", ADS_CONSENT_REQUIRED_EVENT, true).ok();
}
@@ -738,22 +755,24 @@ pub async fn hide_ads_window<R: Runtime>(
}
#[tauri::command]
pub async fn show_ads_consent_overlay<R: Runtime>(
pub async fn show_ads_consent_ui<R: Runtime>(
app: tauri::AppHandle<R>,
notification_enabled: bool,
) -> crate::api::Result<()> {
let mut show_notification = false;
if let Some(webview) = app.webviews().get("ads-window") {
let state = app.state::<RwLock<AdsState>>();
let mut state = state.write().await;
// dont show for hidden ads so consent events cannot re-enable the webview.
if !state.shown {
return Ok(());
}
// Preserve pending consent while the sidebar is hidden, but keep all visibility
// changes gated by `state.shown` so consent events cannot re-enable hidden ads.
state.consent_required = true;
state.consent_notification_enabled = notification_enabled;
state.consent_overlay_shown = false;
show_notification = state.shown && notification_enabled;
if !state.modal_shown {
if state.shown && !state.modal_shown {
let dpr = get_device_pixel_ratio(&app, None);
let (position, size) = get_webview_position(&app, dpr)?;
webview.set_size(size).ok();
@@ -763,13 +782,14 @@ pub async fn show_ads_consent_overlay<R: Runtime>(
}
}
app.emit_to("main", ADS_CONSENT_REQUIRED_EVENT, true).ok();
app.emit_to("main", ADS_CONSENT_REQUIRED_EVENT, show_notification)
.ok();
Ok(())
}
#[tauri::command]
pub async fn show_ads_consent_preferences<R: Runtime>(
pub async fn expand_ads_consent_webview<R: Runtime>(
app: tauri::AppHandle<R>,
) -> crate::api::Result<()> {
if let Some(webview) = app.webviews().get("ads-window") {
@@ -807,53 +827,21 @@ pub async fn open_ads_consent_preferences<R: Runtime>(
{
let state = app.state::<RwLock<AdsState>>();
let mut state = state.write().await;
if !state.consent_required {
state.consent_notification_enabled = false;
}
state.consent_required = true;
state.consent_overlay_shown = false;
}
webview.eval("window.modrinthAdsReopenConsentPreferences?.()")?;
Ok(())
}
/// Restores the ad inventory bounds without resolving the pending consent request.
#[tauri::command]
pub async fn hide_ads_consent_preferences<R: Runtime>(
app: tauri::AppHandle<R>,
) -> crate::api::Result<()> {
if let Some(webview) = app.webviews().get("ads-window") {
let state = app.state::<RwLock<AdsState>>();
let mut state = state.write().await;
state.consent_overlay_shown = false;
if state.shown && !state.modal_shown {
let dpr = get_device_pixel_ratio(&app, None);
let (position, size) = get_webview_position(&app, dpr)?;
webview
.set_bounds(Rect {
position: position.into(),
size: size.into(),
})
.ok();
webview.show().ok();
set_webview_visible_for_window(&app, webview, true);
} else {
webview
.set_position(PhysicalPosition::new(-1000, -1000))
.ok();
webview.hide().ok();
}
}
app.emit_to("main", ADS_CONSENT_REQUIRED_EVENT, true).ok();
webview.eval("window.modrinthPrivacy?.adsReopenConsentPreferences?.()")?;
Ok(())
}
#[tauri::command]
pub async fn hide_ads_consent_overlay<R: Runtime>(
pub async fn finish_ads_consent_flow<R: Runtime>(
app: tauri::AppHandle<R>,
dpr: Option<f32>,
) -> crate::api::Result<()> {
@@ -863,6 +851,7 @@ pub async fn hide_ads_consent_overlay<R: Runtime>(
let should_reload_ads = state.consent_required;
state.consent_required = false;
state.consent_notification_enabled = false;
state.consent_overlay_shown = false;
if state.shown && !state.modal_shown {
@@ -893,13 +882,15 @@ pub async fn hide_ads_consent_overlay<R: Runtime>(
}
#[tauri::command]
pub async fn get_ads_consent_required<R: Runtime>(
pub async fn should_show_ads_consent_popup<R: Runtime>(
app: tauri::AppHandle<R>,
) -> crate::api::Result<bool> {
let state = app.state::<RwLock<AdsState>>();
let state = state.read().await;
Ok(state.shown && state.consent_required)
Ok(state.shown
&& state.consent_required
&& state.consent_notification_enabled)
}
#[tauri::command]
@@ -908,16 +899,18 @@ pub async fn perform_ads_consent_action<R: Runtime>(
action: String,
) -> crate::api::Result<()> {
let script = match action.as_str() {
"accept" => "window.modrinthAdsConsentAction?.('accept')",
"reject" => "window.modrinthAdsConsentAction?.('reject')",
"manage" => "window.modrinthAdsConsentAction?.('manage')",
"accept" => "window.modrinthPrivacy?.adsConsentAction?.('accept')",
"reject" => "window.modrinthPrivacy?.adsConsentAction?.('reject')",
"manage" => "window.modrinthPrivacy?.adsConsentAction?.('manage')",
_ => return Ok(()),
};
let state = app.state::<RwLock<AdsState>>();
let should_perform = {
let state = state.read().await;
state.shown && state.consent_required
state.shown
&& state.consent_required
&& state.consent_notification_enabled
};
if !should_perform {