Skip to main content

tauri_plugin_cef_webview/
registry.rs

1use std::{
2    collections::HashMap,
3    sync::{
4        atomic::{AtomicU64, Ordering},
5        Arc, Mutex,
6    },
7};
8
9use tauri::{
10    webview::Webview, LogicalPosition, LogicalSize, Rect, Runtime, Url,
11};
12
13use crate::{scripts, Config};
14
15/// State managed by the plugin. Holds every child webview created through it.
16pub struct Registry<R: Runtime> {
17    webviews: Mutex<HashMap<String, Webview<R>>>,
18    css_sequence: Arc<AtomicU64>,
19    config: Config,
20}
21
22impl<R: Runtime> Registry<R> {
23    pub(crate) fn new(config: Config) -> Self {
24        Self {
25            webviews: Mutex::new(HashMap::new()),
26            css_sequence: Arc::new(AtomicU64::new(0)),
27            config,
28        }
29    }
30
31    pub(crate) fn config(&self) -> &Config {
32        &self.config
33    }
34
35    pub(crate) fn insert(&self, label: &str, webview: Webview<R>) {
36        self.webviews
37            .lock()
38            .unwrap_or_else(|error| error.into_inner())
39            .insert(label.to_string(), webview);
40    }
41
42    pub(crate) fn remove(&self, label: &str) -> Option<Webview<R>> {
43        self.webviews
44            .lock()
45            .unwrap_or_else(|error| error.into_inner())
46            .remove(label)
47    }
48
49    /// Returns a handle for the child webview registered with `label`.
50    pub fn get(&self, label: &str) -> Option<CefWebview<R>> {
51        self.webviews
52            .lock()
53            .unwrap_or_else(|error| error.into_inner())
54            .get(label)
55            .cloned()
56            .map(|webview| CefWebview {
57                webview,
58                css_sequence: Arc::clone(&self.css_sequence),
59            })
60    }
61
62    /// Labels of every child webview currently managed by the plugin.
63    pub fn labels(&self) -> Vec<String> {
64        self.webviews
65            .lock()
66            .unwrap_or_else(|error| error.into_inner())
67            .keys()
68            .cloned()
69            .collect()
70    }
71}
72
73/// Handle to a child webview created by the plugin.
74#[derive(Clone)]
75pub struct CefWebview<R: Runtime> {
76    pub(crate) webview: Webview<R>,
77    css_sequence: Arc<AtomicU64>,
78}
79
80impl<R: Runtime> CefWebview<R> {
81    /// Label of the child webview.
82    pub fn label(&self) -> &str {
83        self.webview.label()
84    }
85
86    /// Access the underlying Tauri webview.
87    pub fn inner(&self) -> &Webview<R> {
88        &self.webview
89    }
90
91    /// Evaluates JavaScript in the child webview.
92    pub fn eval(&self, js: impl Into<String>) -> tauri::Result<()> {
93        self.webview.eval(js)
94    }
95
96    /// Injects a stylesheet into the child webview and returns its key.
97    pub fn insert_css(&self, css: &str) -> tauri::Result<String> {
98        let key = format!(
99            "cwv-css-{}",
100            self.css_sequence.fetch_add(1, Ordering::Relaxed)
101        );
102        self.webview.eval(scripts::insert_style(&key, css))?;
103        Ok(key)
104    }
105
106    /// Removes a stylesheet previously inserted with [`Self::insert_css`].
107    pub fn remove_inserted_css(&self, key: &str) -> tauri::Result<()> {
108        self.webview.eval(scripts::remove_style(key))
109    }
110
111    /// Navigates the child webview to `url`.
112    pub fn navigate(&self, url: &str) -> Result<(), String> {
113        let url = Url::parse(url).map_err(|error| error.to_string())?;
114        self.webview.navigate(url).map_err(|error| error.to_string())
115    }
116
117    /// Reloads the child webview.
118    pub fn reload(&self) -> tauri::Result<()> {
119        self.webview.reload()
120    }
121
122    /// Opens the child webview devtools (debug builds only).
123    #[cfg(any(debug_assertions, feature = "devtools"))]
124    pub fn open_devtools(&self) {
125        self.webview.open_devtools();
126    }
127
128    /// No-op when devtools support is not compiled in.
129    #[cfg(not(any(debug_assertions, feature = "devtools")))]
130    pub fn open_devtools(&self) {}
131
132    /// Moves and resizes the child webview. Values are logical pixels.
133    pub fn set_rect(&self, x: f64, y: f64, width: f64, height: f64) -> tauri::Result<()> {
134        self.webview.set_bounds(Rect {
135            position: LogicalPosition::new(x, y).into(),
136            size: LogicalSize::new(width, height).into(),
137        })
138    }
139
140    /// Shows or hides the child webview.
141    pub fn set_visible(&self, visible: bool) -> tauri::Result<()> {
142        if visible {
143            self.webview.show()
144        } else {
145            self.webview.hide()
146        }
147    }
148
149    /// Closes the child webview.
150    pub fn close(&self) -> tauri::Result<()> {
151        self.webview.close()
152    }
153}