From 7e45774610340865dcd7e7ba67e8d73cedd17d1f Mon Sep 17 00:00:00 2001 From: Tony <68118705+Legend-Master@users.noreply.github.com> Date: Tue, 21 Jul 2026 14:42:45 +0800 Subject: [PATCH] refactor(fs): cfg gate some ios code (#3510) --- plugins/fs/src/commands.rs | 215 ++++++++++++++++++------------------- 1 file changed, 106 insertions(+), 109 deletions(-) diff --git a/plugins/fs/src/commands.rs b/plugins/fs/src/commands.rs index 963e76abb..fcc38f6bb 100644 --- a/plugins/fs/src/commands.rs +++ b/plugins/fs/src/commands.rs @@ -74,7 +74,7 @@ pub type CommandResult = std::result::Result; /// Represents either a plain PathBuf or a PathHandle that manages security-scoped resources. pub enum PathKind { /// A plain path that doesn't manage security-scoped resources. - #[allow(dead_code)] // only used on mobile + #[cfg(mobile)] // only used on mobile Path(PathBuf), /// A path handle that manages security-scoped resources and will clean them up on drop. Handle(PathHandle), @@ -84,6 +84,7 @@ impl PathKind { /// Get a reference to the underlying path. pub fn as_path(&self) -> &Path { match self { + #[cfg(mobile)] PathKind::Path(p) => p.as_ref(), PathKind::Handle(h) => h.as_ref(), } @@ -92,6 +93,7 @@ impl PathKind { /// Get a reference to the underlying PathBuf. pub fn as_path_buf(&self) -> &PathBuf { match self { + #[cfg(mobile)] PathKind::Path(p) => p, PathKind::Handle(h) => h, } @@ -114,27 +116,13 @@ impl AsRef for PathKind { pub struct FileHandle { file: File, path: PathKind, - #[allow(dead_code)] // Used in Drop implementation + #[cfg(target_os = "ios")] path_: SafeFilePath, - #[allow(dead_code)] // Used in Drop implementation + #[cfg(target_os = "ios")] app_handle: tauri::AppHandle, } impl FileHandle { - fn new( - file: File, - path: PathKind, - path_: SafeFilePath, - app_handle: tauri::AppHandle, - ) -> Self { - Self { - file, - path, - path_, - app_handle, - } - } - /// Get the resolved path. pub fn path(&self) -> &Path { self.path.as_path() @@ -155,41 +143,39 @@ impl DerefMut for FileHandle { } } +#[cfg(target_os = "ios")] impl Drop for FileHandle { fn drop(&mut self) { - #[cfg(target_os = "ios")] - { - // Only clean up if we have a plain PathBuf, not a PathHandle - // PathHandle will handle its own cleanup when it's dropped - if let PathKind::Path(_) = &self.path { - use crate::{FilePath, FsExt}; - // Convert SafeFilePath to FilePath - let file_path: FilePath = match &self.path_ { - SafeFilePath::Url(url) => FilePath::Url(url.clone()), - SafeFilePath::Path(safe_path) => FilePath::Path(safe_path.as_ref().to_owned()), - }; + // Only clean up if we have a plain PathBuf, not a PathHandle + // PathHandle will handle its own cleanup when it's dropped + if let PathKind::Path(_) = &self.path { + use crate::{FilePath, FsExt}; + // Convert SafeFilePath to FilePath + let file_path: FilePath = match &self.path_ { + SafeFilePath::Url(url) => FilePath::Url(url.clone()), + SafeFilePath::Path(safe_path) => FilePath::Path(safe_path.as_ref().to_owned()), + }; - // Only clean up if we're tracking this resource - // If start_accessing_security_scoped_resource was used, it won't be in our tracking - // and we shouldn't interfere - if let FilePath::Url(url) = file_path { - if url.scheme() == "file" { - let security_scoped_resources = - self.app_handle.state::(); + // Only clean up if we're tracking this resource + // If start_accessing_security_scoped_resource was used, it won't be in our tracking + // and we shouldn't interfere + if let FilePath::Url(url) = file_path { + if url.scheme() == "file" { + let security_scoped_resources = + self.app_handle.state::(); - // Only clean up if it's not tracked manually - if !security_scoped_resources.is_tracked_manually(url.as_str()) { - log::debug!("Stopping accessing security-scoped resource for URL: {url} on drop"); - let _ = self - .app_handle - .fs() - .stop_accessing_security_scoped_resource(FilePath::Url( - url.clone(), - )); - security_scoped_resources.remove(url.as_str()); - } else { - log::debug!("Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)"); - } + // Only clean up if it's not tracked manually + if !security_scoped_resources.is_tracked_manually(url.as_str()) { + log::debug!( + "Stopping accessing security-scoped resource for URL: {url} on drop" + ); + let _ = self + .app_handle + .fs() + .stop_accessing_security_scoped_resource(FilePath::Url(url.clone())); + security_scoped_resources.remove(url.as_str()); + } else { + log::debug!("Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)"); } } } @@ -236,38 +222,36 @@ impl AsRef for PathHandle { } } +#[cfg(target_os = "ios")] impl Drop for PathHandle { fn drop(&mut self) { - #[cfg(target_os = "ios")] - { - use crate::{FilePath, FsExt}; - // Convert SafeFilePath to FilePath - let file_path: FilePath = match &self.path_ { - SafeFilePath::Url(url) => FilePath::Url(url.clone()), - SafeFilePath::Path(safe_path) => FilePath::Path(safe_path.as_ref().to_owned()), - }; + use crate::{FilePath, FsExt}; + // Convert SafeFilePath to FilePath + let file_path: FilePath = match &self.path_ { + SafeFilePath::Url(url) => FilePath::Url(url.clone()), + SafeFilePath::Path(safe_path) => FilePath::Path(safe_path.as_ref().to_owned()), + }; - // Only clean up if we're tracking this resource (i.e., resolve_path started it) - // If start_accessing_security_scoped_resource was used, it won't be in our tracking - // and we shouldn't interfere - if let FilePath::Url(url) = file_path { - if url.scheme() == "file" { - let security_scoped_resources = - self.app_handle.state::(); + // Only clean up if we're tracking this resource (i.e., resolve_path started it) + // If start_accessing_security_scoped_resource was used, it won't be in our tracking + // and we shouldn't interfere + if let FilePath::Url(url) = file_path { + if url.scheme() == "file" { + let security_scoped_resources = + self.app_handle.state::(); - // Only clean up if it's not tracked manually - if !security_scoped_resources.is_tracked_manually(url.as_str()) { - log::debug!( - "Stopping accessing security-scoped resource for URL: {url} on drop" - ); - let _ = self - .app_handle - .fs() - .stop_accessing_security_scoped_resource(FilePath::Url(url.clone())); - security_scoped_resources.remove(url.as_str()); - } else { - log::debug!("Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)"); - } + // Only clean up if it's not tracked manually + if !security_scoped_resources.is_tracked_manually(url.as_str()) { + log::debug!( + "Stopping accessing security-scoped resource for URL: {url} on drop" + ); + let _ = self + .app_handle + .fs() + .stop_accessing_security_scoped_resource(FilePath::Url(url.clone())); + security_scoped_resources.remove(url.as_str()); + } else { + log::debug!("Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)"); } } } @@ -288,6 +272,7 @@ pub fn create( path: SafeFilePath, options: Option, ) -> CommandResult { + #[cfg(target_os = "ios")] let path_ = path.clone(); let resolved_path_handle = resolve_path( "create", @@ -303,13 +288,16 @@ pub fn create( resolved_path_handle.display() ) })?; + #[cfg(target_os = "ios")] let app_handle = webview.app_handle().clone(); - let file_handle = FileHandle::new( + let file_handle = FileHandle { file, - PathKind::Handle(resolved_path_handle), + path: PathKind::Handle(resolved_path_handle), + #[cfg(target_os = "ios")] path_, + #[cfg(target_os = "ios")] app_handle, - ); + }; let rid = webview .resources_table() .add(StdFileResource::new(file_handle)); @@ -1417,6 +1405,7 @@ fn resolve_file_in_fs( path: SafeFilePath, open_options: OpenOptions, ) -> CommandResult> { + #[cfg(target_os = "ios")] let path_ = path.clone(); let resolved_path_handle = resolve_path( permission, @@ -1436,13 +1425,16 @@ fn resolve_file_in_fs( ) })?; + #[cfg(target_os = "ios")] let app_handle = webview.app_handle().clone(); - Ok(FileHandle::new( + Ok(FileHandle { file, - PathKind::Handle(resolved_path_handle), + path: PathKind::Handle(resolved_path_handle), + #[cfg(target_os = "ios")] path_, + #[cfg(target_os = "ios")] app_handle, - )) + }) } #[cfg(mobile)] @@ -1456,6 +1448,7 @@ pub fn resolve_file( ) -> CommandResult> { use crate::FsExt; + #[cfg(target_os = "ios")] let path_ = path.clone(); match path { SafeFilePath::Url(url) => { @@ -1463,13 +1456,16 @@ pub fn resolve_file( let file = webview .fs() .open(SafeFilePath::Url(url.clone()), open_options.options)?; + #[cfg(target_os = "ios")] let app_handle = webview.app_handle().clone(); - Ok(FileHandle::new( + Ok(FileHandle { file, - PathKind::Path(resolved_path), + path: PathKind::Path(resolved_path), + #[cfg(target_os = "ios")] path_, + #[cfg(target_os = "ios")] app_handle, - )) + }) } SafeFilePath::Path(path) => resolve_file_in_fs( permission, @@ -1494,36 +1490,37 @@ pub fn resolve_path( // On iOS, start accessing security-scoped resource if the path is a file URL // Only if it hasn't been started already via start_accessing_security_scoped_resource #[cfg(target_os = "ios")] - { - if let SafeFilePath::Url(url) = &path { - if url.scheme() == "file" { - use objc2_foundation::{NSString, NSURL}; + if let SafeFilePath::Url(url) = &path { + if url.scheme() == "file" { + use objc2_foundation::{NSString, NSURL}; - let security_scoped_resources = webview.state::(); + let security_scoped_resources = webview.state::(); - // Check if already active (started via start_accessing_security_scoped_resource) - if !security_scoped_resources.is_tracked_manually(url.as_str()) { - let url_nsstring = NSString::from_str(url.as_str()); - let ns_url = unsafe { NSURL::URLWithString(&url_nsstring) }; - if let Some(ns_url) = ns_url { - // Start accessing the security-scoped resource - // This is required for files outside the app's sandbox (e.g., from file picker) - unsafe { - let success = ns_url.startAccessingSecurityScopedResource(); - if success { - log::debug!("Started accessing security-scoped resource for URL: {} (via resolve_path)", url.as_str()); - // Track it so we know to clean it up - security_scoped_resources.track_manually(url.as_str().to_string()); - } else { - log::warn!("Failed to start accessing security-scoped resource for URL: {}", url.as_str()); - } + // Check if already active (started via start_accessing_security_scoped_resource) + if !security_scoped_resources.is_tracked_manually(url.as_str()) { + let url_nsstring = NSString::from_str(url.as_str()); + let ns_url = unsafe { NSURL::URLWithString(&url_nsstring) }; + if let Some(ns_url) = ns_url { + // Start accessing the security-scoped resource + // This is required for files outside the app's sandbox (e.g., from file picker) + unsafe { + let success = ns_url.startAccessingSecurityScopedResource(); + if success { + log::debug!("Started accessing security-scoped resource for URL: {} (via resolve_path)", url.as_str()); + // Track it so we know to clean it up + security_scoped_resources.track_manually(url.as_str().to_string()); + } else { + log::warn!( + "Failed to start accessing security-scoped resource for URL: {}", + url.as_str() + ); } - } else { - log::debug!("Failed to create NSURL from URL: {}, ignoring security-scoped resource access request", url.as_str()); } } else { - log::debug!("Security-scoped resource already active for URL: {} (started via start_accessing_security_scoped_resource), skipping", url.as_str()); + log::debug!("Failed to create NSURL from URL: {}, ignoring security-scoped resource access request", url.as_str()); } + } else { + log::debug!("Security-scoped resource already active for URL: {} (started via start_accessing_security_scoped_resource), skipping", url.as_str()); } } }