This commit is contained in:
F0RLE 2026-02-06 14:33:41 +11:00 committed by GitHub
commit 0249e56e8b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 104 additions and 1 deletions

View File

@ -4781,6 +4781,30 @@ You may have it installed on another user account, but it is not available for t
webview_builder.with_document_title_changed_handler(document_title_changed_handler)
}
if let Some(permission_request_handler) = pending.permission_request_handler {
webview_builder = webview_builder.with_permission_handler(move |kind| {
let kind = match kind {
wry::PermissionKind::Microphone => tauri_runtime::webview::PermissionKind::Microphone,
wry::PermissionKind::Camera => tauri_runtime::webview::PermissionKind::Camera,
wry::PermissionKind::Geolocation => tauri_runtime::webview::PermissionKind::Geolocation,
wry::PermissionKind::Notifications => tauri_runtime::webview::PermissionKind::Notifications,
wry::PermissionKind::ClipboardRead => tauri_runtime::webview::PermissionKind::ClipboardRead,
wry::PermissionKind::DisplayCapture => {
tauri_runtime::webview::PermissionKind::DisplayCapture
}
wry::PermissionKind::Other => tauri_runtime::webview::PermissionKind::Other,
};
let response = permission_request_handler(kind);
match response {
tauri_runtime::webview::PermissionResponse::Allow => wry::PermissionResponse::Allow,
tauri_runtime::webview::PermissionResponse::Deny => wry::PermissionResponse::Deny,
tauri_runtime::webview::PermissionResponse::Default => wry::PermissionResponse::Default,
}
});
}
let webview_bounds = if let Some(bounds) = webview_attributes.bounds {
let bounds: RectWrapper = bounds.into();
let bounds = bounds.0;

View File

@ -41,6 +41,8 @@ type DocumentTitleChangedHandler = dyn Fn(String) + Send + 'static;
type DownloadHandler = dyn Fn(DownloadEvent) -> bool + Send + Sync;
type PermissionRequestHandler = dyn Fn(PermissionKind) -> PermissionResponse + Send + Sync;
#[cfg(target_os = "ios")]
type InputAccessoryViewBuilderFn = dyn Fn(&objc2_ui_kit::UIView) -> Option<objc2::rc::Retained<objc2_ui_kit::UIView>>
+ Send
@ -69,6 +71,36 @@ pub enum DownloadEvent<'a> {
},
}
/// Permission request response.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PermissionResponse {
/// Permission allowed.
Allow,
/// Permission denied.
Deny,
/// Default behavior.
Default,
}
/// Permission request kind.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PermissionKind {
/// Microphone access permission.
Microphone,
/// Camera access permission.
Camera,
/// Geolocation access permission.
Geolocation,
/// Notifications permission.
Notifications,
/// Clipboard read permission.
ClipboardRead,
/// Display capture permission (for getDisplayMedia).
DisplayCapture,
/// Other unrecognized permission type.
Other,
}
#[cfg(target_os = "android")]
pub struct CreationContext<'a, 'b> {
pub env: &'a mut jni::JNIEnv<'b>,
@ -225,6 +257,8 @@ pub struct PendingWebview<T: UserEvent, R: Runtime<T>> {
pub on_page_load_handler: Option<Box<OnPageLoadHandler>>,
pub download_handler: Option<Arc<DownloadHandler>>,
pub permission_request_handler: Option<Box<PermissionRequestHandler>>,
}
impl<T: UserEvent, R: Runtime<T>> PendingWebview<T, R> {
@ -251,6 +285,7 @@ impl<T: UserEvent, R: Runtime<T>> PendingWebview<T, R> {
web_resource_request_handler: None,
on_page_load_handler: None,
download_handler: None,
permission_request_handler: None,
})
}
}

View File

@ -18,7 +18,9 @@ pub use cookie;
use http::HeaderMap;
use serde::Serialize;
use tauri_macros::default_runtime;
pub use tauri_runtime::webview::{NewWindowFeatures, PageLoadEvent, ScrollBarStyle};
pub use tauri_runtime::webview::{
NewWindowFeatures, PageLoadEvent, PermissionKind, PermissionResponse, ScrollBarStyle,
};
// Remove this re-export in v3
pub use tauri_runtime::Cookie;
#[cfg(desktop)]
@ -65,6 +67,8 @@ pub(crate) type UriSchemeProtocolHandler =
pub(crate) type OnPageLoad<R> = dyn Fn(Webview<R>, PageLoadPayload<'_>) + Send + Sync + 'static;
pub(crate) type OnDocumentTitleChanged<R> = dyn Fn(Webview<R>, String) + Send + 'static;
pub(crate) type DownloadHandler<R> = dyn Fn(Webview<R>, DownloadEvent<'_>) -> bool + Send + Sync;
pub(crate) type PermissionRequestHandler<R> =
dyn Fn(Webview<R>, PermissionKind) -> PermissionResponse + Send + Sync + 'static;
#[derive(Clone, Serialize)]
pub(crate) struct CreatedEvent {
@ -278,6 +282,7 @@ unstable_struct!(
pub(crate) on_page_load_handler: Option<Box<OnPageLoad<R>>>,
pub(crate) document_title_changed_handler: Option<Box<OnDocumentTitleChanged<R>>>,
pub(crate) download_handler: Option<Arc<DownloadHandler<R>>>,
pub(crate) permission_request_handler: Option<Box<PermissionRequestHandler<R>>>,
}
);
@ -356,6 +361,7 @@ async fn create_window(app: tauri::AppHandle) {
on_page_load_handler: None,
document_title_changed_handler: None,
download_handler: None,
permission_request_handler: None,
}
}
@ -435,6 +441,7 @@ async fn create_window(app: tauri::AppHandle) {
on_page_load_handler: None,
document_title_changed_handler: None,
download_handler: None,
permission_request_handler: None,
}
}
@ -697,6 +704,17 @@ tauri::Builder::default()
self
}
/// Defines a closure to be executed when a permission is requested.
pub fn on_permission_request<
F: Fn(Webview<R>, PermissionKind) -> PermissionResponse + Send + Sync + 'static,
>(
mut self,
f: F,
) -> Self {
self.permission_request_handler.replace(Box::new(f));
self
}
pub(crate) fn into_pending_webview<M: Manager<R>>(
mut self,
manager: &M,
@ -776,6 +794,18 @@ tauri::Builder::default()
}
}));
let label_ = pending.label.clone();
let manager_ = manager.manager_owned();
if let Some(handler) = self.permission_request_handler {
pending.permission_request_handler = Some(Box::new(move |kind| {
if let Some(w) = manager_.get_webview(&label_) {
handler(w, kind)
} else {
PermissionResponse::Default
}
}));
}
manager
.manager()
.webview

View File

@ -441,6 +441,20 @@ tauri::Builder::default()
self
}
/// Defines a closure to be executed when a permission is requested.
pub fn on_permission_request<
F: Fn(Webview<R>, crate::webview::PermissionKind) -> crate::webview::PermissionResponse
+ Send
+ Sync
+ 'static,
>(
mut self,
f: F,
) -> Self {
self.webview_builder = self.webview_builder.on_permission_request(f);
self
}
/// Creates a new window.
pub fn build(self) -> crate::Result<WebviewWindow<R>> {
let (window, webview) = self.window_builder.with_webview(self.webview_builder)?;