Skip to main content

host_ext_files/
lib.rs

1//! Files extension — host-mediated save/download actions for SPA tabs.
2//!
3//! Registers as `window.host.ext.files` in the SPA WebView.
4//! Uses the core `__hostCall` bridge (shared pending-promise map).
5
6use host_ext_api::HostExtension;
7
8const HOST_EXT_FILES_SCRIPT: &str = r#"
9(function(){
10    if (!window.host || !window.host.ext) return;
11    window.host.ext.files = Object.freeze({
12        save: function(filename, dataBase64) {
13            return window.__hostCall('hostBridge', 'filesSave', {
14                filename: filename,
15                dataBase64: dataBase64
16            });
17        }
18    });
19})();
20"#;
21
22pub struct FilesExtension;
23
24impl Default for FilesExtension {
25    fn default() -> Self {
26        Self::new()
27    }
28}
29
30impl FilesExtension {
31    pub fn new() -> Self {
32        Self
33    }
34}
35
36impl HostExtension for FilesExtension {
37    fn namespace(&self) -> &str {
38        "files"
39    }
40
41    fn channel(&self) -> &str {
42        "hostBridge"
43    }
44
45    fn inject_script(&self) -> &str {
46        HOST_EXT_FILES_SCRIPT
47    }
48
49    fn handle_message(&self, _method: &str, _params: &str) -> Option<String> {
50        None
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn files_extension_basics() {
60        let ext = FilesExtension::new();
61        assert_eq!(ext.namespace(), "files");
62        assert!(ext.inject_script().contains("window.host.ext.files"));
63        assert!(ext.inject_script().contains("filesSave"));
64    }
65}