ltk_webkit/wpe/
features.rsuse std::ffi::CStr;
use std::sync::Mutex;
use wpe_webkit_sys::*;
static CHOSEN: Mutex<Vec<( String, bool )>> = Mutex::new( Vec::new() );
pub fn set_feature( identifier: &str, enabled: bool )
{
let Ok( mut chosen ) = CHOSEN.lock() else { return };
chosen.retain( |( id, _ )| id != identifier );
chosen.push( ( identifier.to_string(), enabled ) );
}
pub( crate ) unsafe fn apply( webview: *mut WebKitWebView )
{
let Ok( mut chosen ) = CHOSEN.lock() else { return };
if chosen.is_empty() { return; }
let mut unknown = Vec::new();
unsafe
{
let settings = webkit_web_view_get_settings( webview );
let list = webkit_settings_get_all_features();
if settings.is_null() || list.is_null() { return; }
let features: Vec<*mut WebKitFeature> = ( 0..webkit_feature_list_get_length( list ) ).map( |i| webkit_feature_list_get( list, i ) ).collect();
for ( identifier, enabled ) in chosen.iter()
{
match features.iter().find( |&&f| feature_id( f ) == *identifier )
{
Some( &feature ) => webkit_settings_set_feature_enabled( settings, feature, *enabled as glib_sys::gboolean ),
None =>
{
report_unknown( identifier, &features );
unknown.push( identifier.clone() );
}
}
}
webkit_feature_list_unref( list );
}
chosen.retain( |( id, _ )| !unknown.contains( id ) );
}
unsafe fn feature_id( feature: *mut WebKitFeature ) -> String
{
let id = unsafe { webkit_feature_get_identifier( feature ) };
if id.is_null() { String::new() } else { unsafe { CStr::from_ptr( id ) }.to_string_lossy().into_owned() }
}
unsafe fn report_unknown( identifier: &str, features: &[ *mut WebKitFeature ] )
{
let wanted = identifier.trim_end_matches( "Enabled" ).to_lowercase();
let similar: Vec<String> = features.iter()
.map( |&f| ( unsafe { feature_id( f ) }, unsafe { webkit_feature_get_status( f ) } ) )
.filter( |( id, _ )| id.to_lowercase().contains( &wanted ) )
.map( |( id, status )| format!( "{id} ({})", status_name( status ) ) )
.collect();
eprintln!( "ltk-webkit: no WebKit feature {identifier}; similar: {}", if similar.is_empty() { "none".to_string() } else { similar.join( ", " ) } );
}
fn status_name( status: WebKitFeatureStatus ) -> &'static str
{
match status
{
WEBKIT_FEATURE_STATUS_EMBEDDER => "embedder",
WEBKIT_FEATURE_STATUS_UNSTABLE => "unstable",
WEBKIT_FEATURE_STATUS_INTERNAL => "internal",
WEBKIT_FEATURE_STATUS_DEVELOPER => "developer",
WEBKIT_FEATURE_STATUS_TESTABLE => "testable",
WEBKIT_FEATURE_STATUS_PREVIEW => "preview",
WEBKIT_FEATURE_STATUS_STABLE => "stable",
WEBKIT_FEATURE_STATUS_MATURE => "mature",
_ => "unknown",
}
}