Electron FilesystemPermissionRequest 对象详解:fileSystem 权限请求的 details 结构、判定字段与源码级实现

Electron FilesystemPermissionRequest 对象详解:fileSystem 权限请求的 details 结构、判定字段与源码级实现 Electron FilesystemPermissionRequest 对象详解fileSystem 权限请求的 details 结构、判定字段与源码级实现【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electronFilesystemPermissionRequest是 Electron 权限系统中专门用于描述 Web File System API如showDirectoryPicker、FileSystemFileHandle相关能力读写请求的详情对象。它在渲染进程发起fileSystem类型权限请求时作为session.setPermissionRequestHandler的details参数传递给主进程携带filePath、isDirectory、fileAccessType三个关键字段。读完本文你将掌握该对象每个字段的准确含义与来源、如何基于它实现按路径和读写模式精细授权的权限处理器以及 Electron 底层shell/browser/file_system_access/如何构造、传递和最终回收这些权限授予。一、FilesystemPermissionRequest 对象定义该对象的完整定义见 filesystem-permission-request.md属性类型是否可选说明filePathstringoptional该fileSystem请求所针对的路径isDirectorybooleanoptional该fileSystem请求指向的是否为目录fileAccessTypestringoptional该fileSystem请求的访问类型取值为writable或readable它继承自 PermissionRequest 对象因此同时携带两个基础字段继承属性类型说明requestingUrlstring发起请求的 frame 最近加载的 URLisMainFrameboolean发起请求的 frame 是否为主 frame三个字段都标注为optional这与它的使用位置有关在 session.md 中setPermissionRequestHandler的details参数声明为PermissionRequest | FilesystemPermissionRequest | MediaAccessPermissionRequest | OpenExternalPermissionRequest的联合类型——只有当permission参数为fileSystem时details才会是FilesystemPermissionRequest并携带上述三个可选字段其他权限类型如media、display-capture、openExternal则携带对应的其他结构。二、字段在 C 侧的构造位置从源码看这三个字段并非文档层面的约定而是由 Electron 的FileSystemAccessPermissionContext直接构造的。在 file_system_access_permission_context.cc 中PermissionGrantImpl::RequestPermission在把请求转发给权限管理器前构造了如下字典base::DictValue details; details.Set(filePath, base::FilePathToValue(path_info_.path)); details.Set(isDirectory, handle_type_ HandleType::kDirectory); details.Set(fileAccessType, type_ GrantType::kWrite ? writable : readable); const blink::PermissionType type blink::PermissionType::FILE_SYSTEM; permission_manager-RequestPermissionWithDetails( content::PermissionDescriptorUtil:: CreatePermissionDescriptorForPermissionType(type), rfh, origin, rfh-HasTransientUserActivation(), std::move(details), ...);这段代码直接印证了文档中的全部细节权限类型常量是blink::PermissionType::FILE_SYSTEM对应 JS 侧permission参数收到的字符串fileSystemisDirectory由底层句柄类型HandleType::kDirectory / kFile决定fileAccessType由授予类型GrantType::kWrite / kRead二选一映射为writable / readable不存在第三种取值。同样的三个键也在PermissionGrantImpl::GetStatusfile_system_access_permission_context.cc中再次构造用于在已有授权状态下执行权限检查check而非权限请求requestbool granted permission_manager-CheckPermissionWithDetails( blink::PermissionType::FILE_SYSTEM, nullptr, origin_.GetURL(), std::move(details)); return granted ? PermissionStatus::GRANTED : PermissionStatus::DENIED;这解释了 Electron 文档反复强调的“request 与 check 必须配对实现”Web 端多数 API 会先做 permission check走setPermissionCheckHandler检查被拒后再触发 permission request走setPermissionRequestHandler两条路径共用同一份details结构。三、何时会收到 FilesystemPermissionRequest阅读RequestPermission的守卫逻辑file_system_access_permission_context.cc可以看到并不是所有来自渲染进程的 fileSystem 请求都会到达你的 JS 处理器以下情况会被提前拦截并以特定结果码返回你的 handler 不会收到details拦截条件源码行为返回结果码含义请求来自已失效的RenderFrameHostkInvalidFrameframe 已不存在frame 处于“不允许激活”的非活跃状态kInvalidFrame页面无法区分用户拒绝与自动拒绝frame 嵌套在 fenced frame隐私沙箱帧内kInvalidFrame禁止 fenced frame 请求文件系统访问要求用户激活但缺少 transient user activationkNoUserActivation无用户手势不发起权限询问frame 的 origin 与授予记录的 origin 不一致如第三方 iframekThirdPartyContext第三方上下文不允许追加权限已有 GRANTED 状态的授予kRequestAborted已授权则直接复用不再询问因此在主进程处理逻辑里若长时间收不到fileSystem请求可以先排查页面是否处于用户手势之外、是否来自第三方 iframe 等场景。四、在 setPermissionRequestHandler 中消费 FilesystemPermissionRequestdetails的完整联合类型声明见 session.mdses.setPermissionRequestHandler小节。一个只针对fileSystem权限、基于三个字段做精细判定的处理器示例const { session } require(electron) session.defaultSession.setPermissionRequestHandler( (webContents, permission, callback, details) { if (permission ! fileSystem) { // 其他权限按需处理这里默认拒绝 return callback(false) } // details 即 FilesystemPermissionRequest // details.filePath - string | 请求的路径 // details.isDirectory - boolean | 是否目录 // details.fileAccessType - string | writable | readable // 继承字段details.requestingUrl、details.isMainFrame const origin new URL(details.requestingUrl).origin const isWritableRequest details.fileAccessType writable // 示例策略 // 1. 只信任受控 origin // 2. 写请求只允许目录形态的受控工作区路径。 const allowedOrigins [https://trusted.example.com] if (!allowedOrigins.includes(origin)) return callback(false) if (isWritableRequest !details.filePath.startsWith(/workspace)) { return callback(false) } callback(true) } )注意两点必须同时实现setPermissionCheckHandler。session.md 明确说明“you must also implementsetPermissionCheckHandlerto get complete permission handling”。check handler 的details对象同样以可选形式携带filePath/isDirectory/fileAccessType三个fileSystem专有字段见 session.md与 request handler 的FilesystemPermissionRequest字段保持一致session.defaultSession.setPermissionCheckHandler( (webContents, permission, requestingOrigin, details) { if (permission fileSystem) { // 检查阶段同样可读取 details.filePath / isDirectory / fileAccessType return details?.fileAccessType ! writable || (details?.filePath ?? ).startsWith(/workspace) } return false } )子 frame 发起的请求应以details.requestingUrl继承自PermissionRequest判断真实来源而不是直接取webContents.getURL()——session.md 在 handler 参数说明中对此有专门提醒。五、配套的 file-system-access-restricted 事件路径黑名单拦截除权限请求/检查两条通道外Electron 还针对“受保护路径”提供了独立的拦截事件。FileSystemAccessPermissionContext在构造时会异步生成系统级路径黑名单GenerateBlockPaths当某次用户操作如拖拽文件、打开/保存对话框选择命中的路径被列入黑名单时DidCheckPathAgainstBlocklist会向对应session发出file-system-access-restricted事件file_system_access_permission_context.ccif (should_block) { // ... 构造 details 后 session-Get()-Emit( file-system-access-restricted, details, base::BindRepeating( FileSystemAccessPermissionContext::OnRestrictedPathResult, ...)); }注意该事件的details是{ origin, isDirectory, path }路径字段名为path而非filePath回调接收allow | deny | tryAgain三种动作与FilesystemPermissionRequest的字段不完全相同请勿混用。官方示例session.md展示了弹出消息框让用户三选一、再回调不同动作的完整流程。六、授权的生命周期自动授予、继承与回收理解fileAccessType字段的实际约束力需要看 Electron 如何判定哪些访问需要询问、哪些直接放行。GetReadPermissionGrant/GetWritePermissionGrantfile_system_access_permission_context.cc中的规则是读权限自动授予父目录已有可读授权时子路径直接继承为 GRANTEDAncestorHasActivePermissionfile_system_access_permission_context.cc沿path.DirName()逐级上溯拖拽drag drop获得的所有句柄自动授予读权限写权限自动授予仅“保存”save dialog场景会自动授予写权限打开open、拖拽、从存储恢复load from storage均不授予写权限目录形态的 open/save 不自动授予读权限句柄类型变化即撤销同一路径从目录变为文件或反之时旧授权被置为 DENIED 并重建这也是isDirectory必须随请求传递的原因——授权是按“路径 句柄类型”精确登记的。授权并非永久有效NavigatedAwayFromOrigin会为离开原 origin 的 origin 启动一个 5 秒的清理定时器常量kPermissionRevocationTimeout base::Seconds(5)file_system_access_permission_context.cc到期后CleanupPermissions调用RevokeActiveGrants将该 origin 的读/写授予统一重置为 ASKfile_system_access_permission_context.cc。这意味着即使你在 handler 中callback(true)授权也仅在该 origin 存活期间有效origin 导航离开 5 秒后后续访问会重新走 check → request 流程你的 handler 会再次收到同一结构的FilesystemPermissionRequest。七、要点小结FilesystemPermissionRequest继承PermissionRequest新增filePath、isDirectory、fileAccessType仅writable/readable两值三个可选字段完整定义见 filesystem-permission-request.md它仅在permission fileSystem时作为details出现在setPermissionRequestHandler中字段由 file_system_access_permission_context.cc 中RequestPermission/GetStatus直接构造键名与文档一一对应子 frame、无用户手势、fenced frame、第三方 origin 等请求会在到达 JS 层之前被 C 守卫拦截排查“收不到请求”时应先核对这些前置条件request handler 与 check handler 需成对实现check 的details也携带同名三字段系统敏感路径的拦截走独立的file-system-access-restricted事件origin/isDirectory/path 三值回调不要与FilesystemPermissionRequest的字段混淆授权按“origin × 路径 × 句柄类型 × 读写类型”精确登记父目录授权可被子路径继承且 origin 导航离开约 5 秒后授权自动回收。【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考