Feasibility of Pluginization in Tauri Applications for GUI Development with Rust

There are several approaches to pluginization, including <span>Webview</span>, iframe, and shadow DOM. Essentially, a <span>sandbox</span> is needed to load untrusted third-party resources without affecting the main application.

Webview

Whether in Tauri or Electron, the structure of the application window is generally as follows:

+-------------------------------------+
|              Window                            |
|  +-------------------------------+  |
|  |          WindowApp                   |  |
|  |  +----------------------------+  |  |
|  |  |        Webview                     |  |  |
|  |  +----------------------------+  |  |
|  +--------------------------------+  |
+-------------------------------------+

Electron can use the <span><webview></span> tag on the page to load third-party resources. However, Tauri cannot do this.

What is the reason?

The reason is that Electron is essentially a browser, forked from the <span>chromium</span> project, which gives it absolute control over webview and allows for modifications as desired. However, Tauri is merely a “kernel wrapper”; it uses Microsoft Edge WebView2 on Windows, WKWebView on macOS, and webkitgtk on Linux. This limits its ability to modify webview.

Therefore, using it in the same way as Electron is not feasible.

Electron also has something called <span>BrowserView</span>, which has a structure like this:

+-------------------------------------+
|              Window                           |
|  +-------------------------------+  |
|  |          WindowApp                   |  |
|  +-------------------------------+  |
|  +-------------------------------+  |
|  |          BrowserView                   |  |
|  +-------------------------------+  |
+-------------------------------------+

Since Tauri’s goal is simply to act as a wrapper, it does not have anything similar to <span>BrowserView</span>.

iframe

iframe is actually an embedded tag in the browser DOM standard, and using iframe to implement a plugin container is certainly feasible. However, there are significant limitations with iframes. For example, if you want to embed certain websites, many will use the <span>X-Frame-Options</span> header to prevent third-party embedding of <span><iframe></span> tags. Additionally, since iframes are purely front-end embedded, they cannot be converted into independent windows. Other limitations exist, but I am not deeply familiar with the pitfalls of iframes.

shadow DOM

shadow DOM allows the browser to encapsulate templates, stylesheets, attributes, JavaScript code, etc., into a standalone DOM element, creating an isolated environment. From this perspective, it can somewhat serve as a “sandbox”.

However, shadow DOM is not completely isolated. There are ways to break encapsulation, as JavaScript can still access and manipulate it.

The Best Option

From the above, webview seems to be a better choice, but Tauri cannot directly nest one webview inside another.

Fortunately, Tauri supports adding multiple webviews to a single Window.

let window = tauri::window::WindowBuilder::new(app, "main")
        .inner_size(width, height)
        .build()?;

      let _webview1 = window.add_child(
        tauri::webview::WebviewBuilder::new("main1", WebviewUrl::App(Default::default()))
          .auto_resize(),
        LogicalPosition::new(0., 0.),
        LogicalSize::new(width / 2., height / 2.),
      )?;

      let _webview2 = window.add_child(
        tauri::webview::WebviewBuilder::new(
          "main2",
          WebviewUrl::External("https://github.com/tauri-apps/tauri".parse().unwrap()),
        )
        .auto_resize(),
        LogicalPosition::new(width / 2., 0.),
        LogicalSize::new(width / 2., height / 2.),
      )?;

The above code will result in the following structure:

+-------------------------------------+
|            Window                             |
|  +-------------------------------+  |
|  |        WindowApp                     |  |
|  |  +---------------------------+  |  |
|  |  | &lt;webview&gt; |  | &lt;webview&gt; |  |
|  |  +---------------------------+  |  |
|  +-------------------------------+  |
+-------------------------------------+

At the same time, we also need to add the <span>unstable</span> feature for Tauri:

tauri = { version = "2.8.4", features = ["unstable"] }

Leave a Comment