use std::ffi::{ c_char, CStr };
use std::sync::{ Mutex, Weak };
use glib_sys::*;
use gobject_sys::*;
use wpe_webkit_sys::*;
use super::Inner;
type DecidePolicyFn = unsafe extern "C" fn( *mut WebKitWebView, *mut WebKitPolicyDecision, WebKitPolicyDecisionType, gpointer ) -> gboolean;
pub( crate ) unsafe fn connect( webview: *mut WebKitWebView, inner: Weak<Mutex<Inner>> )
{
let data = Box::into_raw( Box::new( inner ) ) as gpointer;
unsafe
{
let handler = std::mem::transmute::<DecidePolicyFn, unsafe extern "C" fn()>( on_decide_policy );
g_signal_connect_data(
webview as *mut GObject,
b"decide-policy\0".as_ptr() as *const c_char,
Some( handler ),
data,
Some( drop_weak ),
0,
);
}
}
unsafe extern "C" fn drop_weak( data: gpointer, _closure: *mut GClosure )
{
if data.is_null() { return; }
drop( unsafe { Box::from_raw( data as *mut Weak<Mutex<Inner>> ) } );
}
unsafe extern "C" fn on_decide_policy(
_webview: *mut WebKitWebView,
decision: *mut WebKitPolicyDecision,
kind: WebKitPolicyDecisionType,
user_data: gpointer,
) -> gboolean
{
if decision.is_null() { return 0; }
match kind
{
WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION =>
{
let Some( inner ) = unsafe { &*( user_data as *const Weak<Mutex<Inner>> ) }.upgrade() else { return 0 };
unsafe { super::navigation::decide( decision, &inner ) }
}
WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION =>
{
let uri = unsafe { navigation_uri( decision as *mut WebKitNavigationPolicyDecision ) };
if let Some( uri ) = uri
{
let inner = unsafe { &*( user_data as *const Weak<Mutex<Inner>> ) }.upgrade();
if let Some( inner ) = inner
{
if let Ok( mut g ) = inner.lock() { g.new_window_requests.push( uri ); }
}
}
unsafe { webkit_policy_decision_ignore( decision ); }
1
}
WEBKIT_POLICY_DECISION_TYPE_RESPONSE =>
{
let response = decision as *mut WebKitResponsePolicyDecision;
if unsafe { webkit_response_policy_decision_is_mime_type_supported( response ) } != 0
{
return 0;
}
unsafe { webkit_policy_decision_download( decision ); }
1
}
_ => 0,
}
}
unsafe fn navigation_uri( decision: *mut WebKitNavigationPolicyDecision ) -> Option<String>
{
unsafe
{
let action = webkit_navigation_policy_decision_get_navigation_action( decision );
if action.is_null() { return None; }
let request = webkit_navigation_action_get_request( action );
if request.is_null() { return None; }
let uri = webkit_uri_request_get_uri( request );
if uri.is_null() { return None; }
Some( CStr::from_ptr( uri ).to_string_lossy().into_owned() )
}
}