mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-12-15 13:41:39 +03:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
9e31dd5ccb
5
.changes/window-request-handler.md
Normal file
5
.changes/window-request-handler.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch
|
||||
---
|
||||
|
||||
Added `WindowBuilder::on_web_resource_request`, which allows customizing the tauri custom protocol response.
|
@ -219,10 +219,10 @@ struct HttpRequestWrapper(HttpRequest);
|
||||
|
||||
impl From<&WryHttpRequest> for HttpRequestWrapper {
|
||||
fn from(req: &WryHttpRequest) -> Self {
|
||||
Self(HttpRequest {
|
||||
body: req.body.clone(),
|
||||
head: HttpRequestPartsWrapper::from(req.head.clone()).0,
|
||||
})
|
||||
Self(HttpRequest::new_internal(
|
||||
HttpRequestPartsWrapper::from(req.head.clone()).0,
|
||||
req.body.clone(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,9 +242,10 @@ impl From<HttpResponseParts> for HttpResponsePartsWrapper {
|
||||
struct HttpResponseWrapper(WryHttpResponse);
|
||||
impl From<HttpResponse> for HttpResponseWrapper {
|
||||
fn from(response: HttpResponse) -> Self {
|
||||
let (parts, body) = response.into_parts();
|
||||
Self(WryHttpResponse {
|
||||
body: response.body,
|
||||
head: HttpResponsePartsWrapper::from(response.head).0,
|
||||
body,
|
||||
head: HttpResponsePartsWrapper::from(parts).0,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1466,6 +1467,26 @@ pub struct Wry {
|
||||
tray_context: TrayContext,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Wry {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut d = f.debug_struct("Wry");
|
||||
d.field("main_thread_id", &self.main_thread_id)
|
||||
.field("global_shortcut_manager", &self.global_shortcut_manager)
|
||||
.field(
|
||||
"global_shortcut_manager_handle",
|
||||
&self.global_shortcut_manager_handle,
|
||||
)
|
||||
.field("clipboard_manager", &self.clipboard_manager)
|
||||
.field("clipboard_manager_handle", &self.clipboard_manager_handle)
|
||||
.field("event_loop", &self.event_loop)
|
||||
.field("windows", &self.windows)
|
||||
.field("web_context", &self.web_context);
|
||||
#[cfg(feature = "system-tray")]
|
||||
d.field("tray_context", &self.tray_context);
|
||||
d.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A handle to the Wry runtime.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WryHandle {
|
||||
|
@ -17,8 +17,8 @@ use super::{
|
||||
///
|
||||
/// - **Linux:** Headers are not exposed.
|
||||
pub struct Request {
|
||||
pub head: RequestParts,
|
||||
pub body: Vec<u8>,
|
||||
head: RequestParts,
|
||||
body: Vec<u8>,
|
||||
}
|
||||
|
||||
/// Component parts of an HTTP `Request`
|
||||
@ -47,6 +47,17 @@ impl Request {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `Request` with the given head and body.
|
||||
///
|
||||
/// # Stability
|
||||
///
|
||||
/// This API is used internally. It may have breaking changes in the future.
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
pub fn new_internal(head: RequestParts, body: Vec<u8>) -> Request {
|
||||
Request { head, body }
|
||||
}
|
||||
|
||||
/// Returns a reference to the associated HTTP method.
|
||||
#[inline]
|
||||
pub fn method(&self) -> &Method {
|
||||
@ -72,6 +83,10 @@ impl Request {
|
||||
}
|
||||
|
||||
/// Consumes the request returning the head and body RequestParts.
|
||||
///
|
||||
/// # Stability
|
||||
///
|
||||
/// This API is used internally. It may have breaking changes in the future.
|
||||
#[inline]
|
||||
pub fn into_parts(self) -> (RequestParts, Vec<u8>) {
|
||||
(self.head, self.body)
|
||||
|
@ -32,8 +32,8 @@ type Result<T> = core::result::Result<T, Box<dyn std::error::Error>>;
|
||||
/// ```
|
||||
///
|
||||
pub struct Response {
|
||||
pub head: ResponseParts,
|
||||
pub body: Vec<u8>,
|
||||
head: ResponseParts,
|
||||
body: Vec<u8>,
|
||||
}
|
||||
|
||||
/// Component parts of an HTTP `Response`
|
||||
@ -42,16 +42,16 @@ pub struct Response {
|
||||
/// header fields.
|
||||
#[derive(Clone)]
|
||||
pub struct ResponseParts {
|
||||
/// The response's status
|
||||
/// The response's status.
|
||||
pub status: StatusCode,
|
||||
|
||||
/// The response's version
|
||||
/// The response's version.
|
||||
pub version: Version,
|
||||
|
||||
/// The response's headers
|
||||
/// The response's headers.
|
||||
pub headers: HeaderMap<HeaderValue>,
|
||||
|
||||
/// The response's mimetype type
|
||||
/// The response's mimetype type.
|
||||
pub mimetype: Option<String>,
|
||||
}
|
||||
|
||||
@ -74,16 +74,39 @@ impl Response {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `StatusCode`.
|
||||
/// Consumes the response returning the head and body ResponseParts.
|
||||
///
|
||||
/// # Stability
|
||||
///
|
||||
/// This API is used internally. It may have breaking changes in the future.
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
pub fn into_parts(self) -> (ResponseParts, Vec<u8>) {
|
||||
(self.head, self.body)
|
||||
}
|
||||
|
||||
/// Sets the status code.
|
||||
#[inline]
|
||||
pub fn set_status(&mut self, status: StatusCode) {
|
||||
self.head.status = status;
|
||||
}
|
||||
|
||||
/// Returns the [`StatusCode`].
|
||||
#[inline]
|
||||
pub fn status(&self) -> StatusCode {
|
||||
self.head.status
|
||||
}
|
||||
|
||||
/// Sets the mimetype.
|
||||
#[inline]
|
||||
pub fn set_mimetype(&mut self, mimetype: Option<String>) {
|
||||
self.head.mimetype = mimetype;
|
||||
}
|
||||
|
||||
/// Returns a reference to the mime type.
|
||||
#[inline]
|
||||
pub fn mimetype(&self) -> Option<String> {
|
||||
self.head.mimetype.clone()
|
||||
pub fn mimetype(&self) -> Option<&String> {
|
||||
self.head.mimetype.as_ref()
|
||||
}
|
||||
|
||||
/// Returns a reference to the associated version.
|
||||
@ -92,12 +115,24 @@ impl Response {
|
||||
self.head.version
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the associated header field map.
|
||||
#[inline]
|
||||
pub fn headers_mut(&mut self) -> &mut HeaderMap<HeaderValue> {
|
||||
&mut self.head.headers
|
||||
}
|
||||
|
||||
/// Returns a reference to the associated header field map.
|
||||
#[inline]
|
||||
pub fn headers(&self) -> &HeaderMap<HeaderValue> {
|
||||
&self.head.headers
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the associated HTTP body.
|
||||
#[inline]
|
||||
pub fn body_mut(&mut self) -> &mut Vec<u8> {
|
||||
&mut self.body
|
||||
}
|
||||
|
||||
/// Returns a reference to the associated HTTP body.
|
||||
#[inline]
|
||||
pub fn body(&self) -> &Vec<u8> {
|
||||
|
@ -311,7 +311,7 @@ pub trait ClipboardManager: Debug + Clone + Send + Sync {
|
||||
}
|
||||
|
||||
/// The webview runtime interface.
|
||||
pub trait Runtime: Sized + 'static {
|
||||
pub trait Runtime: Debug + Sized + 'static {
|
||||
/// The message dispatcher.
|
||||
type Dispatcher: Dispatch<Runtime = Self>;
|
||||
/// The runtime handle type.
|
||||
|
@ -23,6 +23,7 @@ use crate::{
|
||||
sealed::{ManagerBase, RuntimeOrDispatch},
|
||||
utils::config::{Config, WindowUrl},
|
||||
utils::{assets::Assets, Env},
|
||||
window::WindowBuilder,
|
||||
Context, Invoke, InvokeError, InvokeResponse, Manager, Scopes, StateManager, Window,
|
||||
};
|
||||
|
||||
@ -386,15 +387,12 @@ macro_rules! shared_app_impl {
|
||||
WebviewAttributes,
|
||||
),
|
||||
{
|
||||
let (window_builder, webview_attributes) = setup(
|
||||
<R::Dispatcher as Dispatch>::WindowBuilder::new(),
|
||||
WebviewAttributes::new(url),
|
||||
);
|
||||
self.create_new_window(PendingWindow::new(
|
||||
window_builder,
|
||||
webview_attributes,
|
||||
label,
|
||||
)?)
|
||||
let mut builder = WindowBuilder::<R>::new(self, label, url);
|
||||
let (window_builder, webview_attributes) =
|
||||
setup(builder.window_builder, builder.webview_attributes);
|
||||
builder.window_builder = window_builder;
|
||||
builder.webview_attributes = webview_attributes;
|
||||
builder.build()
|
||||
}
|
||||
|
||||
#[cfg(feature = "system-tray")]
|
||||
@ -1310,9 +1308,10 @@ impl<R: Runtime> Builder<R> {
|
||||
let mut main_window = None;
|
||||
|
||||
for pending in self.pending_windows {
|
||||
let pending = app
|
||||
.manager
|
||||
.prepare_window(app.handle.clone(), pending, &window_labels)?;
|
||||
let pending =
|
||||
app
|
||||
.manager
|
||||
.prepare_window(app.handle.clone(), pending, &window_labels, None)?;
|
||||
let detached = app.runtime.as_ref().unwrap().create_window(pending)?;
|
||||
let _window = app.manager.attach_window(app.handle(), detached);
|
||||
#[cfg(feature = "updater")]
|
||||
|
@ -174,7 +174,6 @@ pub type Result<T> = std::result::Result<T, Error>;
|
||||
/// A task to run on the main thread.
|
||||
pub type SyncTask = Box<dyn FnOnce() + Send>;
|
||||
|
||||
use crate::runtime::window::PendingWindow;
|
||||
use serde::Serialize;
|
||||
use std::{collections::HashMap, fmt, sync::Arc};
|
||||
|
||||
@ -600,7 +599,7 @@ pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
|
||||
/// Prevent implementation details from leaking out of the [`Manager`] trait.
|
||||
pub(crate) mod sealed {
|
||||
use crate::{app::AppHandle, manager::WindowManager};
|
||||
use tauri_runtime::{Runtime, RuntimeHandle};
|
||||
use tauri_runtime::Runtime;
|
||||
|
||||
/// A running [`Runtime`] or a dispatcher to it.
|
||||
pub enum RuntimeOrDispatch<'r, R: Runtime> {
|
||||
@ -614,51 +613,12 @@ pub(crate) mod sealed {
|
||||
Dispatch(R::Dispatcher),
|
||||
}
|
||||
|
||||
#[derive(Clone, serde::Serialize)]
|
||||
struct WindowCreatedEvent {
|
||||
label: String,
|
||||
}
|
||||
|
||||
/// Managed handle to the application runtime.
|
||||
pub trait ManagerBase<R: Runtime> {
|
||||
/// The manager behind the [`Managed`] item.
|
||||
fn manager(&self) -> &WindowManager<R>;
|
||||
|
||||
fn runtime(&self) -> RuntimeOrDispatch<'_, R>;
|
||||
fn managed_app_handle(&self) -> AppHandle<R>;
|
||||
|
||||
/// Creates a new [`Window`] on the [`Runtime`] and attaches it to the [`Manager`].
|
||||
fn create_new_window(
|
||||
&self,
|
||||
pending: crate::PendingWindow<R>,
|
||||
) -> crate::Result<crate::Window<R>> {
|
||||
use crate::runtime::Dispatch;
|
||||
let labels = self.manager().labels().into_iter().collect::<Vec<_>>();
|
||||
let pending = self
|
||||
.manager()
|
||||
.prepare_window(self.managed_app_handle(), pending, &labels)?;
|
||||
let window = match self.runtime() {
|
||||
RuntimeOrDispatch::Runtime(runtime) => runtime.create_window(pending),
|
||||
RuntimeOrDispatch::RuntimeHandle(handle) => handle.create_window(pending),
|
||||
RuntimeOrDispatch::Dispatch(mut dispatcher) => dispatcher.create_window(pending),
|
||||
}
|
||||
.map(|window| {
|
||||
self
|
||||
.manager()
|
||||
.attach_window(self.managed_app_handle(), window)
|
||||
})?;
|
||||
|
||||
self.manager().emit_filter(
|
||||
"tauri://window-created",
|
||||
None,
|
||||
Some(WindowCreatedEvent {
|
||||
label: window.label().into(),
|
||||
}),
|
||||
|w| w != &window,
|
||||
)?;
|
||||
|
||||
Ok(window)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,11 +129,16 @@ fn set_csp<R: Runtime>(
|
||||
let csp = Csp::DirectiveMap(csp).to_string();
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
*asset = asset.replacen(tauri_utils::html::CSP_TOKEN, &csp, 1);
|
||||
*asset = set_html_csp(asset, &csp);
|
||||
}
|
||||
csp
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn set_html_csp(html: &str, csp: &str) -> String {
|
||||
html.replacen(tauri_utils::html::CSP_TOKEN, csp, 1)
|
||||
}
|
||||
|
||||
// inspired by https://github.com/rust-lang/rust/blob/1be5c8f90912c446ecbdc405cbc4a89f9acd20fd/library/alloc/src/str.rs#L260-L297
|
||||
fn replace_with_callback<F: FnMut() -> String>(
|
||||
original: &str,
|
||||
@ -383,6 +388,9 @@ impl<R: Runtime> WindowManager<R> {
|
||||
label: &str,
|
||||
window_labels: &[String],
|
||||
app_handle: AppHandle<R>,
|
||||
web_resource_request_handler: Option<
|
||||
Box<dyn Fn(&HttpRequest, &mut HttpResponse) + Send + Sync>,
|
||||
>,
|
||||
) -> crate::Result<PendingWindow<R>> {
|
||||
let is_init_global = self.inner.config.build.with_global_tauri;
|
||||
let plugin_init = self
|
||||
@ -470,7 +478,10 @@ impl<R: Runtime> WindowManager<R> {
|
||||
}
|
||||
|
||||
if !registered_scheme_protocols.contains(&"tauri".into()) {
|
||||
pending.register_uri_scheme_protocol("tauri", self.prepare_uri_scheme_protocol());
|
||||
pending.register_uri_scheme_protocol(
|
||||
"tauri",
|
||||
self.prepare_uri_scheme_protocol(web_resource_request_handler),
|
||||
);
|
||||
registered_scheme_protocols.push("tauri".into());
|
||||
}
|
||||
|
||||
@ -788,6 +799,9 @@ impl<R: Runtime> WindowManager<R> {
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn prepare_uri_scheme_protocol(
|
||||
&self,
|
||||
web_resource_request_handler: Option<
|
||||
Box<dyn Fn(&HttpRequest, &mut HttpResponse) + Send + Sync>,
|
||||
>,
|
||||
) -> Box<dyn Fn(&HttpRequest) -> Result<HttpResponse, Box<dyn std::error::Error>> + Send + Sync>
|
||||
{
|
||||
let manager = self.clone();
|
||||
@ -801,11 +815,28 @@ impl<R: Runtime> WindowManager<R> {
|
||||
.to_string()
|
||||
.replace("tauri://localhost", "");
|
||||
let asset = manager.get_asset(path)?;
|
||||
let mut response = HttpResponseBuilder::new().mimetype(&asset.mime_type);
|
||||
if let Some(csp) = asset.csp_header {
|
||||
response = response.header("Content-Security-Policy", csp);
|
||||
let mut builder = HttpResponseBuilder::new().mimetype(&asset.mime_type);
|
||||
if let Some(csp) = &asset.csp_header {
|
||||
builder = builder.header("Content-Security-Policy", csp);
|
||||
}
|
||||
response.body(asset.bytes)
|
||||
let mut response = builder.body(asset.bytes)?;
|
||||
if let Some(handler) = &web_resource_request_handler {
|
||||
handler(request, &mut response);
|
||||
|
||||
// if it's an HTML file, we need to set the CSP meta tag on Linux
|
||||
#[cfg(target_os = "linux")]
|
||||
if let (Some(original_csp), Some(response_csp)) = (
|
||||
asset.csp_header,
|
||||
response.headers().get("Content-Security_Policy"),
|
||||
) {
|
||||
let response_csp = String::from_utf8_lossy(response_csp.as_bytes());
|
||||
if response_csp != original_csp {
|
||||
let body = set_html_csp(&String::from_utf8_lossy(response.body()), &response_csp);
|
||||
*response.body_mut() = body.as_bytes().to_vec();
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(response)
|
||||
})
|
||||
}
|
||||
|
||||
@ -990,6 +1021,9 @@ impl<R: Runtime> WindowManager<R> {
|
||||
app_handle: AppHandle<R>,
|
||||
mut pending: PendingWindow<R>,
|
||||
window_labels: &[String],
|
||||
web_resource_request_handler: Option<
|
||||
Box<dyn Fn(&HttpRequest, &mut HttpResponse) + Send + Sync>,
|
||||
>,
|
||||
) -> crate::Result<PendingWindow<R>> {
|
||||
if self.windows_lock().contains_key(&pending.label) {
|
||||
return Err(crate::Error::WindowLabelAlreadyExists(pending.label));
|
||||
@ -1043,7 +1077,13 @@ impl<R: Runtime> WindowManager<R> {
|
||||
|
||||
if is_local {
|
||||
let label = pending.label.clone();
|
||||
pending = self.prepare_pending_window(pending, &label, window_labels, app_handle.clone())?;
|
||||
pending = self.prepare_pending_window(
|
||||
pending,
|
||||
&label,
|
||||
window_labels,
|
||||
app_handle.clone(),
|
||||
web_resource_request_handler,
|
||||
)?;
|
||||
pending.ipc_handler = Some(self.prepare_ipc_handler(app_handle.clone()));
|
||||
}
|
||||
|
||||
|
@ -489,6 +489,7 @@ impl TrayHandle for MockTrayHandler {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MockRuntime {
|
||||
pub context: RuntimeContext,
|
||||
global_shortcut_manager: MockGlobalShortcutManager,
|
||||
|
@ -15,6 +15,7 @@ use crate::{
|
||||
hooks::{InvokePayload, InvokeResponder},
|
||||
manager::WindowManager,
|
||||
runtime::{
|
||||
http::{Request as HttpRequest, Response as HttpResponse},
|
||||
menu::Menu,
|
||||
monitor::Monitor as RuntimeMonitor,
|
||||
webview::{WebviewAttributes, WindowBuilder as _},
|
||||
@ -22,7 +23,7 @@ use crate::{
|
||||
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
|
||||
DetachedWindow, JsEventListenerKey, PendingWindow, WindowEvent,
|
||||
},
|
||||
Dispatch, Runtime, UserAttentionType,
|
||||
Dispatch, Runtime, RuntimeHandle, UserAttentionType,
|
||||
},
|
||||
sealed::ManagerBase,
|
||||
sealed::RuntimeOrDispatch,
|
||||
@ -37,11 +38,17 @@ use windows::Win32::Foundation::HWND;
|
||||
use tauri_macros::default_runtime;
|
||||
|
||||
use std::{
|
||||
fmt,
|
||||
hash::{Hash, Hasher},
|
||||
path::PathBuf,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
#[derive(Clone, Serialize)]
|
||||
struct WindowCreatedEvent {
|
||||
label: String,
|
||||
}
|
||||
|
||||
/// Monitor descriptor.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@ -98,14 +105,27 @@ pub enum RuntimeHandleOrDispatch<R: Runtime> {
|
||||
|
||||
/// A builder for a webview window managed by Tauri.
|
||||
#[default_runtime(crate::Wry, wry)]
|
||||
#[derive(Debug)]
|
||||
pub struct WindowBuilder<R: Runtime> {
|
||||
manager: WindowManager<R>,
|
||||
runtime: RuntimeHandleOrDispatch<R>,
|
||||
app_handle: AppHandle<R>,
|
||||
label: String,
|
||||
pub(crate) window_builder: <R::Dispatcher as Dispatch>::WindowBuilder,
|
||||
webview_attributes: WebviewAttributes,
|
||||
pub(crate) webview_attributes: WebviewAttributes,
|
||||
web_resource_request_handler: Option<Box<dyn Fn(&HttpRequest, &mut HttpResponse) + Send + Sync>>,
|
||||
}
|
||||
|
||||
impl<R: Runtime> fmt::Debug for WindowBuilder<R> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("WindowBuilder")
|
||||
.field("manager", &self.manager)
|
||||
.field("runtime", &self.runtime)
|
||||
.field("app_handle", &self.app_handle)
|
||||
.field("label", &self.label)
|
||||
.field("window_builder", &self.window_builder)
|
||||
.field("webview_attributes", &self.webview_attributes)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Runtime> ManagerBase<R> for WindowBuilder<R> {
|
||||
@ -141,16 +161,92 @@ impl<R: Runtime> WindowBuilder<R> {
|
||||
label: label.into(),
|
||||
window_builder: <R::Dispatcher as Dispatch>::WindowBuilder::new(),
|
||||
webview_attributes: WebviewAttributes::new(url),
|
||||
web_resource_request_handler: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines a closure to be executed when the webview makes an HTTP request for a web resource, allowing you to modify the response.
|
||||
///
|
||||
/// Currently only implemented for the `tauri` URI protocol.
|
||||
///
|
||||
/// **NOTE:** Currently this is **not** executed when using external URLs such as a development server,
|
||||
/// but it might be implemented in the future. **Always** check the request URL.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use tauri::{
|
||||
/// utils::config::{Csp, CspDirectiveSources, WindowUrl},
|
||||
/// runtime::http::header::HeaderValue,
|
||||
/// window::WindowBuilder,
|
||||
/// };
|
||||
/// use std::collections::HashMap;
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(|app| {
|
||||
/// WindowBuilder::new(app, "core", WindowUrl::App("index.html".into()))
|
||||
/// .on_web_resource_request(|request, response| {
|
||||
/// if request.uri().starts_with("tauri://") {
|
||||
/// // if we have a CSP header, Tauri is loading an HTML file
|
||||
/// // for this example, let's dynamically change the CSP
|
||||
/// if let Some(csp) = response.headers_mut().get_mut("Content-Security-Policy") {
|
||||
/// // use the tauri helper to parse the CSP policy to a map
|
||||
/// let mut csp_map: HashMap<String, CspDirectiveSources> = Csp::Policy(csp.to_str().unwrap().to_string()).into();
|
||||
/// csp_map.entry("script-src".to_string()).or_insert_with(Default::default).push("'unsafe-inline'");
|
||||
/// // use the tauri helper to get a CSP string from the map
|
||||
/// let csp_string = Csp::from(csp_map).to_string();
|
||||
/// *csp = HeaderValue::from_str(&csp_string).unwrap();
|
||||
/// }
|
||||
/// }
|
||||
/// })
|
||||
/// .build()
|
||||
/// .unwrap();
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
pub fn on_web_resource_request<F: Fn(&HttpRequest, &mut HttpResponse) + Send + Sync + 'static>(
|
||||
mut self,
|
||||
f: F,
|
||||
) -> Self {
|
||||
self.web_resource_request_handler.replace(Box::new(f));
|
||||
self
|
||||
}
|
||||
|
||||
/// Creates a new webview window.
|
||||
pub fn build(self) -> crate::Result<Window<R>> {
|
||||
self.create_new_window(PendingWindow::new(
|
||||
pub fn build(mut self) -> crate::Result<Window<R>> {
|
||||
let web_resource_request_handler = self.web_resource_request_handler.take();
|
||||
let pending = PendingWindow::new(
|
||||
self.window_builder.clone(),
|
||||
self.webview_attributes.clone(),
|
||||
self.label.clone(),
|
||||
)?)
|
||||
)?;
|
||||
let labels = self.manager().labels().into_iter().collect::<Vec<_>>();
|
||||
let pending = self.manager().prepare_window(
|
||||
self.managed_app_handle(),
|
||||
pending,
|
||||
&labels,
|
||||
web_resource_request_handler,
|
||||
)?;
|
||||
let window = match self.runtime() {
|
||||
RuntimeOrDispatch::Runtime(runtime) => runtime.create_window(pending),
|
||||
RuntimeOrDispatch::RuntimeHandle(handle) => handle.create_window(pending),
|
||||
RuntimeOrDispatch::Dispatch(mut dispatcher) => dispatcher.create_window(pending),
|
||||
}
|
||||
.map(|window| {
|
||||
self
|
||||
.manager()
|
||||
.attach_window(self.managed_app_handle(), window)
|
||||
})?;
|
||||
|
||||
self.manager().emit_filter(
|
||||
"tauri://window-created",
|
||||
None,
|
||||
Some(WindowCreatedEvent {
|
||||
label: window.label().into(),
|
||||
}),
|
||||
|w| w != &window,
|
||||
)?;
|
||||
|
||||
Ok(window)
|
||||
}
|
||||
|
||||
// --------------------------------------------- Window builder ---------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user