ltk_webkit/wpe/
content_filter.rsuse std::ffi::{ c_void, CString };
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::ptr;
use std::sync::OnceLock;
use std::sync::atomic::{ AtomicUsize, Ordering };
use gio::ffi::GAsyncResult;
use glib_sys::{ g_bytes_new, g_bytes_unref, g_error_free, gpointer, GError };
use gobject_sys::{ g_object_unref, GObject };
use wpe_webkit_sys::*;
static MANAGER: OnceLock<usize> = OnceLock::new();
static GENERATION: AtomicUsize = AtomicUsize::new( 0 );
pub( crate ) fn user_content_manager() -> *mut WebKitUserContentManager
{
*MANAGER.get_or_init( || unsafe { webkit_user_content_manager_new() } as usize ) as *mut WebKitUserContentManager
}
pub fn set_content_filter( store_dir: &Path, identifier: &str, rules_json: &str )
{
let ( Ok( dir ), Ok( identifier ) ) = ( CString::new( store_dir.as_os_str().as_bytes() ), CString::new( identifier ) ) else { return };
let generation = GENERATION.fetch_add( 1, Ordering::Relaxed ) + 1;
unsafe
{
let store = webkit_user_content_filter_store_new( dir.as_ptr() );
if store.is_null() { return; }
let bytes = g_bytes_new( rules_json.as_ptr() as *const c_void, rules_json.len() );
webkit_user_content_filter_store_save( store, identifier.as_ptr(), bytes, ptr::null_mut(), Some( on_saved ), generation as gpointer );
g_bytes_unref( bytes );
g_object_unref( store as *mut GObject );
}
}
pub fn remove_content_filters()
{
GENERATION.fetch_add( 1, Ordering::Relaxed );
unsafe { webkit_user_content_manager_remove_all_filters( user_content_manager() ); }
}
unsafe extern "C" fn on_saved( source: *mut GObject, result: *mut GAsyncResult, user_data: gpointer )
{
let mut err: *mut GError = ptr::null_mut();
unsafe
{
let filter = webkit_user_content_filter_store_save_finish( source as *mut WebKitUserContentFilterStore, result, &mut err );
if filter.is_null()
{
eprintln!( "[ltk-webkit] content filter not compiled: {}", super::error_message_or_default( err, "unknown" ) );
if !err.is_null() { g_error_free( err ); }
return;
}
if user_data as usize == GENERATION.load( Ordering::Relaxed )
{
let manager = user_content_manager();
webkit_user_content_manager_remove_all_filters( manager );
webkit_user_content_manager_add_filter( manager, filter );
}
webkit_user_content_filter_unref( filter );
}
}