From f089964a3cf3014987aca24a7e7d6cae83e67d8a Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Wed, 22 May 2024 22:05:52 -0300 Subject: [PATCH] fix(linux): async custom protocol crashing sending response (#1276) --- .changes/fix-custom-protocol-async-linux.md | 5 ++ examples/async_custom_protocol.rs | 3 +- examples/custom_protocol.rs | 3 +- examples/custom_titlebar.rs | 3 +- examples/gtk_multiwebview.rs | 6 ++- examples/multiwebview.rs | 6 ++- examples/multiwindow.rs | 3 +- examples/streaming.rs | 3 +- examples/wgpu.rs | 6 ++- src/webkitgtk/web_context.rs | 60 +++++++++++++-------- src/wkwebview/mod.rs | 6 ++- 11 files changed, 63 insertions(+), 41 deletions(-) create mode 100644 .changes/fix-custom-protocol-async-linux.md diff --git a/.changes/fix-custom-protocol-async-linux.md b/.changes/fix-custom-protocol-async-linux.md new file mode 100644 index 000000000..2ebd8cf0f --- /dev/null +++ b/.changes/fix-custom-protocol-async-linux.md @@ -0,0 +1,5 @@ +--- +"wry": patch +--- + +Fixes `with_asynchronous_custom_protocol` crashing when sending the response on Linux. diff --git a/examples/async_custom_protocol.rs b/examples/async_custom_protocol.rs index 3d4026faa..757c5bbd9 100644 --- a/examples/async_custom_protocol.rs +++ b/examples/async_custom_protocol.rs @@ -9,9 +9,8 @@ use tao::{ event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }; -use wry::http::Request; use wry::{ - http::{header::CONTENT_TYPE, Response}, + http::{header::CONTENT_TYPE, Request, Response}, WebViewBuilder, }; diff --git a/examples/custom_protocol.rs b/examples/custom_protocol.rs index 55e315ba1..b24adc8a4 100644 --- a/examples/custom_protocol.rs +++ b/examples/custom_protocol.rs @@ -9,9 +9,8 @@ use tao::{ event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }; -use wry::http::Request; use wry::{ - http::{header::CONTENT_TYPE, Response}, + http::{header::CONTENT_TYPE, Request, Response}, WebViewBuilder, }; diff --git a/examples/custom_titlebar.rs b/examples/custom_titlebar.rs index 74fe9992e..b6c5ca9bc 100644 --- a/examples/custom_titlebar.rs +++ b/examples/custom_titlebar.rs @@ -8,8 +8,7 @@ use tao::{ event_loop::{ControlFlow, EventLoopBuilder}, window::{CursorIcon, ResizeDirection, Window, WindowBuilder}, }; -use wry::http::Request; -use wry::WebViewBuilder; +use wry::{http::Request, WebViewBuilder}; #[derive(Debug)] enum HitTestResult { diff --git a/examples/gtk_multiwebview.rs b/examples/gtk_multiwebview.rs index 93078c871..6e6533996 100644 --- a/examples/gtk_multiwebview.rs +++ b/examples/gtk_multiwebview.rs @@ -7,8 +7,10 @@ use tao::{ event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }; -use wry::dpi::{LogicalPosition, LogicalSize}; -use wry::{Rect, WebViewBuilder}; +use wry::{ + dpi::{LogicalPosition, LogicalSize}, + Rect, WebViewBuilder, +}; fn main() -> wry::Result<()> { let event_loop = EventLoop::new(); diff --git a/examples/multiwebview.rs b/examples/multiwebview.rs index 569ef7594..8380b1320 100644 --- a/examples/multiwebview.rs +++ b/examples/multiwebview.rs @@ -7,8 +7,10 @@ use winit::{ event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }; -use wry::dpi::{LogicalPosition, LogicalSize}; -use wry::{Rect, WebViewBuilder}; +use wry::{ + dpi::{LogicalPosition, LogicalSize}, + Rect, WebViewBuilder, +}; fn main() -> wry::Result<()> { #[cfg(any( diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs index d178b4bb1..1a95c09a1 100644 --- a/examples/multiwindow.rs +++ b/examples/multiwindow.rs @@ -8,8 +8,7 @@ use tao::{ event_loop::{ControlFlow, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget}, window::{Window, WindowBuilder, WindowId}, }; -use wry::http::Request; -use wry::{WebView, WebViewBuilder}; +use wry::{http::Request, WebView, WebViewBuilder}; enum UserEvent { CloseWindow(WindowId), diff --git a/examples/streaming.rs b/examples/streaming.rs index 858fbc38e..86a9a0dc2 100644 --- a/examples/streaming.rs +++ b/examples/streaming.rs @@ -14,9 +14,8 @@ use tao::{ event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }; -use wry::http::Request; use wry::{ - http::{header::*, Response}, + http::{header::*, Request, Response}, WebViewBuilder, }; diff --git a/examples/wgpu.rs b/examples/wgpu.rs index 9b816f73a..c452e48f5 100644 --- a/examples/wgpu.rs +++ b/examples/wgpu.rs @@ -4,8 +4,10 @@ use winit::{ event_loop::{ControlFlow, EventLoop}, window::Window, }; -use wry::dpi::{LogicalPosition, LogicalSize}; -use wry::{Rect, WebViewBuilder}; +use wry::{ + dpi::{LogicalPosition, LogicalSize}, + Rect, WebViewBuilder, +}; async fn run(event_loop: EventLoop<()>, window: Window) { let size = window.inner_size(); diff --git a/src/webkitgtk/web_context.rs b/src/webkitgtk/web_context.rs index db9209d26..df12dec89 100644 --- a/src/webkitgtk/web_context.rs +++ b/src/webkitgtk/web_context.rs @@ -5,7 +5,7 @@ //! Unix platform extensions for [`WebContext`](super::WebContext). use crate::{web_context::WebContextData, Error, RequestAsyncResponder}; -use gtk::glib; +use gtk::glib::{self, MainContext}; use http::{header::CONTENT_TYPE, HeaderName, HeaderValue, Request, Response as HttpResponse}; use soup::{MessageHeaders, MessageHeadersType}; use std::{ @@ -21,9 +21,9 @@ use std::{ }; use webkit2gtk::{ ApplicationInfo, AutomationSessionExt, CookiePersistentStorage, DownloadExt, LoadEvent, - SecurityManagerExt, URIRequest, URIRequestExt, URISchemeRequestExt, URISchemeResponse, - URISchemeResponseExt, UserContentManager, WebContext, WebContextExt as Webkit2gtkContextExt, - WebView, WebViewExt, + SecurityManagerExt, URIRequest, URIRequestExt, URISchemeRequest, URISchemeRequestExt, + URISchemeResponse, URISchemeResponseExt, UserContentManager, WebContext, + WebContextExt as Webkit2gtkContextExt, WebView, WebViewExt, }; #[derive(Debug)] @@ -361,28 +361,31 @@ where } }; - let request_ = request.clone(); + let request_ = MainThreadRequest(request.clone()); let responder: Box>)> = Box::new(move |http_response| { - let buffer = http_response.body(); - let input = gtk::gio::MemoryInputStream::from_bytes(>k::glib::Bytes::from(buffer)); - let content_type = http_response - .headers() - .get(CONTENT_TYPE) - .and_then(|h| h.to_str().ok()); - - let response = URISchemeResponse::new(&input, buffer.len() as i64); - response.set_status(http_response.status().as_u16() as u32, None); - if let Some(content_type) = content_type { - response.set_content_type(content_type); - } + MainContext::default().invoke(move || { + let buffer = http_response.body(); + let input = gtk::gio::MemoryInputStream::from_bytes(>k::glib::Bytes::from(buffer)); + let content_type = http_response + .headers() + .get(CONTENT_TYPE) + .and_then(|h| h.to_str().ok()); + + let response = URISchemeResponse::new(&input, buffer.len() as i64); + response.set_status(http_response.status().as_u16() as u32, None); + if let Some(content_type) = content_type { + response.set_content_type(content_type); + } + + let headers = MessageHeaders::new(MessageHeadersType::Response); + for (name, value) in http_response.headers().into_iter() { + headers.append(name.as_str(), value.to_str().unwrap_or("")); + } + response.set_http_headers(headers); + request_.finish_with_response(&response); + }); - let headers = MessageHeaders::new(MessageHeadersType::Response); - for (name, value) in http_response.headers().into_iter() { - headers.append(name.as_str(), value.to_str().unwrap_or("")); - } - response.set_http_headers(headers); - request_.finish_with_response(&response); }); #[cfg(feature = "tracing")] @@ -399,6 +402,17 @@ where Ok(()) } +struct MainThreadRequest(URISchemeRequest); + +impl MainThreadRequest { + fn finish_with_response(&self, response: &URISchemeResponse) { + self.0.finish_with_response(response); + } +} + +unsafe impl Send for MainThreadRequest {} +unsafe impl Sync for MainThreadRequest {} + #[derive(Debug)] struct WebviewUriRequest { webview: WebView, diff --git a/src/wkwebview/mod.rs b/src/wkwebview/mod.rs index f4dd5f402..ad629dd7a 100644 --- a/src/wkwebview/mod.rs +++ b/src/wkwebview/mod.rs @@ -32,8 +32,10 @@ use std::{ sync::{Arc, Mutex}, }; -use core_graphics::base::CGFloat; -use core_graphics::geometry::{CGPoint, CGRect, CGSize}; +use core_graphics::{ + base::CGFloat, + geometry::{CGPoint, CGRect, CGSize}, +}; use objc::{ declare::ClassDecl,