Skip to main content

tauri_plugin_cef_webview/
lib.rs

1//! Embed native child webviews in a Tauri application and control them from
2//! the frontend with a plain `<webview>` element.
3
4mod commands;
5mod frames;
6#[cfg(feature = "offscreen")]
7mod offscreen;
8mod registry;
9mod scripts;
10
11pub use registry::{CefWebview, Registry};
12
13use tauri::{
14    plugin::{Builder as PluginBuilder, TauriPlugin},
15    Manager, Runtime,
16};
17
18/// Installed into every application page so `<webview>` works without imports.
19/// Registered as a plugin initialization script, so it runs before any page
20/// script in every webview, including windows created from the app config.
21const HOST_RUNTIME: &str = include_str!("element.js.inc");
22
23/// Plugin configuration.
24#[derive(Clone, Debug, Default)]
25pub struct Config {
26    /// JavaScript injected into every child webview before page scripts run.
27    pub js: Vec<String>,
28    /// CSS injected into every child webview.
29    pub css: Vec<String>,
30    /// Create child webviews off-screen and paint them into the host page.
31    ///
32    /// Requires `runtime(cef_runtime())` from this crate and the `offscreen`
33    /// feature; falls back to native child webviews otherwise.
34    pub offscreen: bool,
35}
36
37impl Config {
38    /// Adds a JavaScript snippet applied to every child webview.
39    pub fn js(mut self, script: impl Into<String>) -> Self {
40        self.js.push(script.into());
41        self
42    }
43
44    /// Adds a stylesheet applied to every child webview.
45    pub fn css(mut self, css: impl Into<String>) -> Self {
46        self.css.push(css.into());
47        self
48    }
49
50    /// Renders child webviews into the host page instead of native child views.
51    pub fn offscreen(mut self, offscreen: bool) -> Self {
52        self.offscreen = offscreen;
53        self
54    }
55}
56
57/// Initializes the plugin with the default configuration.
58pub fn init<R: Runtime>() -> TauriPlugin<R> {
59    init_with(Config::default())
60}
61
62/// Initializes the plugin with a custom configuration.
63pub fn init_with<R: Runtime>(config: Config) -> TauriPlugin<R> {
64    PluginBuilder::new("cef-webview")
65        .initialization_script(HOST_RUNTIME)
66        .invoke_handler(tauri::generate_handler![
67            commands::create,
68            commands::set_rect,
69            commands::set_visible,
70            commands::destroy,
71            commands::eval,
72            commands::insert_css,
73            commands::remove_inserted_css,
74            commands::navigate,
75            commands::reload,
76            commands::open_devtools,
77            commands::call,
78            commands::frame,
79        ])
80        .setup(move |app, _api| {
81            app.manage(Registry::<R>::new(config));
82            Ok(())
83        })
84        .build()
85}
86
87/// Access the plugin registry from a Tauri app handle.
88pub trait CefWebviewExt<R: Runtime> {
89    /// Returns the plugin registry, which exposes [`Registry::get`].
90    fn cef_webviews(&self) -> tauri::State<'_, Registry<R>>;
91}
92
93impl<R: Runtime, M: Manager<R>> CefWebviewExt<R> for M {
94    fn cef_webviews(&self) -> tauri::State<'_, Registry<R>> {
95        self.state::<Registry<R>>()
96    }
97}
98
99/// Returns the CEF runtime with windowless rendering enabled, required by
100/// [`Config::offscreen`].
101///
102/// ```text
103/// # use tauri::Manager;
104/// tauri::Builder::default()
105///     .runtime(tauri_plugin_cef_webview::cef_runtime())
106///     .plugin(tauri_plugin_cef_webview::init_with(
107///         tauri_plugin_cef_webview::Config::default().offscreen(true),
108///     ))
109/// # .run(tauri::generate_context!())
110/// # .unwrap();
111/// ```
112#[cfg(feature = "offscreen")]
113pub fn cef_runtime() -> tauri_runtime_cef::Cef {
114    use tauri_runtime_cef::Cef;
115    Cef::default().with_settings(|settings| {
116        settings.windowless_rendering_enabled = 1;
117    })
118}