Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import androidx.compose.ui.awt.SwingPanel
import io.github.kdroidfilter.webview.cookie.WryCookieManager
import io.github.kdroidfilter.webview.jsbridge.WebViewJsBridge
import io.github.kdroidfilter.webview.jsbridge.parseJsMessage
import io.github.kdroidfilter.webview.request.WebRequest
import io.github.kdroidfilter.webview.request.WebRequestInterceptResult
import kotlinx.coroutines.delay

actual class WebViewFactoryParam(
Expand Down Expand Up @@ -120,6 +122,41 @@ actual fun ActualWebView(
}
}

DisposableEffect(nativeWebView) {
val listener: (String) -> Boolean = a@{
if (navigator.requestInterceptor == null) {
return@a true
}

val webRequest =
WebRequest(
url = it,
headers = mutableMapOf(),
isForMainFrame = true,
isRedirect = true,
method = "GET",
)

return@a when (val interceptResult = navigator.requestInterceptor.onInterceptUrlRequest(webRequest, navigator)) {
WebRequestInterceptResult.Allow -> true

WebRequestInterceptResult.Reject -> false

is WebRequestInterceptResult.Modify -> {
interceptResult.request.let { modified ->
navigator.stopLoading()
navigator.loadUrl(modified.url, modified.headers)
}
false //no jump?
}
}
}
nativeWebView.addNavigateListener(listener)
onDispose {
nativeWebView.removeNavigateListener(listener)
}
}

SwingPanel(
modifier = modifier,
factory = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ class WryWebViewPanel(
private var pendingBounds: Bounds? = null
private var boundsTimer: Timer? = null

private val handlers = mutableListOf<(String) -> Boolean>()

private val handler = object : NavigationHandler {
override fun handleNavigation(url: String): Boolean = handlers.any { it(url) }
}

init {
layout = BorderLayout()
add(host, BorderLayout.CENTER)
Expand Down Expand Up @@ -71,6 +77,14 @@ class WryWebViewPanel(
scheduleCreateIfNeeded()
}

fun addNavigateListener(data: (String) -> Boolean) {
handlers.add(data)
}

fun removeNavigateListener(data: (String) -> Boolean) {
handlers.remove(data)
}

fun loadUrl(url: String) {
loadUrl(url, emptyMap())
}
Expand Down Expand Up @@ -332,9 +346,16 @@ class WryWebViewPanel(
return try {
webviewId =
if (userAgent == null) {
NativeBindings.createWebview(handleSnapshot, width, height, initialUrl)
NativeBindings.createWebview(handleSnapshot, width, height, initialUrl, handler)
} else {
NativeBindings.createWebviewWithUserAgent(handleSnapshot, width, height, initialUrl, userAgent)
NativeBindings.createWebviewWithUserAgent(
handleSnapshot,
width,
height,
initialUrl,
userAgent,
handler
)
}
updateBounds()
startGtkPumpIfNeeded()
Expand All @@ -350,6 +371,7 @@ class WryWebViewPanel(
pendingHtml = null
NativeBindings.loadHtml(id, html)
}

urlWithHeaders != null && headers.isNotEmpty() -> {
pendingUrlWithHeaders = null
pendingHeaders = emptyMap()
Expand All @@ -370,9 +392,16 @@ class WryWebViewPanel(
thread(name = "wry-webview-create", isDaemon = true) {
val createdId = try {
if (userAgent == null) {
NativeBindings.createWebview(handleSnapshot, width, height, initialUrl)
NativeBindings.createWebview(handleSnapshot, width, height, initialUrl, handler)
} else {
NativeBindings.createWebviewWithUserAgent(handleSnapshot, width, height, initialUrl, userAgent)
NativeBindings.createWebviewWithUserAgent(
handleSnapshot,
width,
height,
initialUrl,
userAgent,
handler
)
}
} catch (e: RuntimeException) {
System.err.println("Failed to create Wry webview: ${e.message}")
Expand Down Expand Up @@ -406,11 +435,13 @@ class WryWebViewPanel(
pendingHtml = null
NativeBindings.loadHtml(createdId, html)
}

urlWithHeaders != null && headers.isNotEmpty() -> {
pendingUrlWithHeaders = null
pendingHeaders = emptyMap()
NativeBindings.loadUrlWithHeaders(createdId, urlWithHeaders, headers)
}

pendingUrl != initialUrl -> {
NativeBindings.loadUrl(createdId, pendingUrl)
}
Expand Down Expand Up @@ -557,7 +588,13 @@ class WryWebViewPanel(
}
} else if (IS_MAC) {
if (contentHandle != 0L && contentHandle != windowHandle) {
log("resolveParentHandle skiko content=0x${contentHandle.toString(16)} window=0x${windowHandle.toString(16)} (macOS content)")
log(
"resolveParentHandle skiko content=0x${contentHandle.toString(16)} window=0x${
windowHandle.toString(
16
)
} (macOS content)"
)
return ParentHandle(contentHandle.toULong(), false)
}
if (windowHandle != 0L) {
Expand All @@ -570,7 +607,13 @@ class WryWebViewPanel(
}
} else {
if (contentHandle != 0L) {
log("resolveParentHandle skiko content=0x${contentHandle.toString(16)} window=0x${windowHandle.toString(16)}")
log(
"resolveParentHandle skiko content=0x${contentHandle.toString(16)} window=0x${
windowHandle.toString(
16
)
}"
)
return ParentHandle(contentHandle.toULong(), false)
}
if (windowHandle != 0L) {
Expand Down Expand Up @@ -642,8 +685,8 @@ class WryWebViewPanel(
}

private object NativeBindings {
fun createWebview(parentHandle: ULong, width: Int, height: Int, url: String): ULong {
return io.github.kdroidfilter.webview.wry.createWebview(parentHandle, width, height, url)
fun createWebview(parentHandle: ULong, width: Int, height: Int, url: String, handler: NavigationHandler): ULong {
return io.github.kdroidfilter.webview.wry.createWebview(parentHandle, width, height, url, handler)
}

fun createWebviewWithUserAgent(
Expand All @@ -652,13 +695,15 @@ private object NativeBindings {
height: Int,
url: String,
userAgent: String,
handler: NavigationHandler,
): ULong {
return io.github.kdroidfilter.webview.wry.createWebviewWithUserAgent(
parentHandle,
width,
height,
url,
userAgent,
handler,
)
}

Expand Down
23 changes: 18 additions & 5 deletions wrywebview/src/main/rust/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ mod state;
use std::str::FromStr;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::sync::OnceLock;

use wry::cookie::time::OffsetDateTime;
use wry::cookie::{Cookie, Expiration, SameSite};
Expand Down Expand Up @@ -172,12 +171,19 @@ macro_rules! wry_log {
// WebView Creation
// ============================================================================

#[uniffi::export(callback_interface)]
pub trait NavigationHandler: Send + Sync {
/// Return true to allow navigation, false to cancel.
fn handle_navigation(&self, url: String) -> bool;
}

fn create_webview_inner(
parent_handle: u64,
width: i32,
height: i32,
url: String,
user_agent: Option<String>,
nav_handler: Option<Box<dyn NavigationHandler>>,
) -> Result<u64, WebViewError> {
let user_agent =
user_agent.and_then(|ua| {
Expand Down Expand Up @@ -216,11 +222,16 @@ fn create_webview_inner(

let webview = builder
.with_navigation_handler(move |new_url| {
if let Some(handler) = &nav_handler {
return handler.handle_navigation(new_url.to_string());
}

wry_log!("[wrywebview] navigation_handler url={}", new_url);
state_for_nav.is_loading.store(true, Ordering::SeqCst);
if let Err(e) = state_for_nav.update_current_url(new_url.clone()) {
wry_log!("[wrywebview] navigation_handler state update failed: {}", e);
}

true
})
.with_on_page_load_handler(move |event, url| {
Expand Down Expand Up @@ -315,16 +326,17 @@ pub fn create_webview(
width: i32,
height: i32,
url: String,
nav_handler: Option<Box<dyn NavigationHandler>>
) -> Result<u64, WebViewError> {
#[cfg(target_os = "linux")]
{
return run_on_gtk_thread(move || {
create_webview_inner(parent_handle, width, height, url, None)
create_webview_inner(parent_handle, width, height, url, None, nav_handler)
});
}

#[cfg(not(target_os = "linux"))]
run_on_main_thread(move || create_webview_inner(parent_handle, width, height, url, None))
run_on_main_thread(move || create_webview_inner(parent_handle, width, height, url, None, nav_handler))
}

#[uniffi::export]
Expand All @@ -334,16 +346,17 @@ pub fn create_webview_with_user_agent(
height: i32,
url: String,
user_agent: Option<String>,
nav_handler: Option<Box<dyn NavigationHandler>>
) -> Result<u64, WebViewError> {
#[cfg(target_os = "linux")]
{
return run_on_gtk_thread(move || {
create_webview_inner(parent_handle, width, height, url, user_agent)
create_webview_inner(parent_handle, width, height, url, user_agent, nav_handler)
});
}

#[cfg(not(target_os = "linux"))]
run_on_main_thread(move || create_webview_inner(parent_handle, width, height, url, user_agent))
run_on_main_thread(move || create_webview_inner(parent_handle, width, height, url, user_agent,nav_handler))
}

// ============================================================================
Expand Down