@@ -44,7 +44,10 @@ use std::{
4444use tauri_macros:: default_runtime;
4545use tauri_utils:: {
4646 assets:: { AssetKey , CspHash } ,
47- html:: { CSP_TOKEN , INVOKE_KEY_TOKEN , SCRIPT_NONCE_TOKEN , STYLE_NONCE_TOKEN } ,
47+ html:: {
48+ inject_csp, parse as parse_html, CSP_TOKEN , INVOKE_KEY_TOKEN , SCRIPT_NONCE_TOKEN ,
49+ STYLE_NONCE_TOKEN ,
50+ } ,
4851} ;
4952use url:: Url ;
5053
@@ -271,6 +274,21 @@ impl<R: Runtime> WindowManager<R> {
271274 key
272275 }
273276
277+ fn csp ( & self ) -> Option < String > {
278+ if cfg ! ( feature = "custom-protocol" ) {
279+ self . inner . config . tauri . security . csp . clone ( )
280+ } else {
281+ self
282+ . inner
283+ . config
284+ . tauri
285+ . security
286+ . dev_csp
287+ . clone ( )
288+ . or_else ( || self . inner . config . tauri . security . csp . clone ( ) )
289+ }
290+ }
291+
274292 /// Checks whether the invoke key is valid or not.
275293 ///
276294 /// An invoke key is valid if it was generated by this manager instance.
@@ -545,19 +563,7 @@ impl<R: Runtime> WindowManager<R> {
545563 asset = asset. replacen ( INVOKE_KEY_TOKEN , & self . generate_invoke_key ( ) . to_string ( ) , 1 ) ;
546564
547565 if is_html {
548- let csp = if cfg ! ( feature = "custom-protocol" ) {
549- self . inner . config . tauri . security . csp . clone ( )
550- } else {
551- self
552- . inner
553- . config
554- . tauri
555- . security
556- . dev_csp
557- . clone ( )
558- . or_else ( || self . inner . config . tauri . security . csp . clone ( ) )
559- } ;
560- if let Some ( mut csp) = csp {
566+ if let Some ( mut csp) = self . csp ( ) {
561567 let hash_strings = self . inner . assets . csp_hashes ( & asset_path) . fold (
562568 CspHashStrings :: default ( ) ,
563569 |mut acc, hash| {
@@ -764,7 +770,7 @@ impl<R: Runtime> WindowManager<R> {
764770 if self . windows_lock ( ) . contains_key ( & pending. label ) {
765771 return Err ( crate :: Error :: WindowLabelAlreadyExists ( pending. label ) ) ;
766772 }
767- let ( is_local, url) = match & pending. webview_attributes . url {
773+ let ( is_local, mut url) = match & pending. webview_attributes . url {
768774 WindowUrl :: App ( path) => {
769775 let url = self . get_url ( ) ;
770776 (
@@ -773,18 +779,32 @@ impl<R: Runtime> WindowManager<R> {
773779 if path. to_str ( ) != Some ( "index.html" ) {
774780 url
775781 . join ( & * path. to_string_lossy ( ) )
776- . map_err ( crate :: Error :: InvalidUrl ) ?
777- . to_string ( )
782+ . map_err ( crate :: Error :: InvalidUrl )
783+ // this will never fail
784+ . unwrap ( )
778785 } else {
779- url. to_string ( )
786+ url. into_owned ( )
780787 } ,
781788 )
782789 }
783- WindowUrl :: External ( url) => ( url. scheme ( ) == "tauri" , url. to_string ( ) ) ,
790+ WindowUrl :: External ( url) => ( url. scheme ( ) == "tauri" , url. clone ( ) ) ,
784791 _ => unimplemented ! ( ) ,
785792 } ;
786793
787- pending. url = url;
794+ if let Some ( csp) = self . csp ( ) {
795+ if url. scheme ( ) == "data" {
796+ if let Ok ( data_url) = data_url:: DataUrl :: process ( url. as_str ( ) ) {
797+ let ( body, _) = data_url. decode_to_vec ( ) . unwrap ( ) ;
798+ let html = String :: from_utf8_lossy ( & body) . into_owned ( ) ;
799+ // naive way to check if it's an html
800+ if html. contains ( '<' ) && html. contains ( '>' ) {
801+ let mut document = parse_html ( html) ;
802+ inject_csp ( & mut document, & csp) ;
803+ url. set_path ( & format ! ( "text/html,{}" , document. to_string( ) ) ) ;
804+ }
805+ }
806+ }
807+ }
788808
789809 if is_local {
790810 let label = pending. label . clone ( ) ;
@@ -796,6 +816,8 @@ impl<R: Runtime> WindowManager<R> {
796816 pending. file_drop_handler = Some ( self . prepare_file_drop ( app_handle) ) ;
797817 }
798818
819+ pending. url = url. to_string ( ) ;
820+
799821 // in `Windows`, we need to force a data_directory
800822 // but we do respect user-specification
801823 #[ cfg( any( target_os = "linux" , target_os = "windows" ) ) ]
0 commit comments