Mountain/Environment/WebviewProvider.rs
1
2//! # WebviewProvider (Environment)
3//!
4//! Implements the `WebviewProvider` trait for `MountainEnvironment`, providing
5//! the core logic for creating, managing, and securing Webview panels.
6//!
7//! ## Architecture
8//!
9//! ```text
10//! Extension → CreateWebviewPanel → WebviewProvider → Tauri WebviewWindow
11//! │ │
12//! └→ IPC → Cocoon ◄───────────┘
13//! ```
14//!
15//! ## Webview types
16//!
17//! - **Panel** - sidebar or panel webview (non-floating)
18//! - **Editor** - webview as custom editor (full editor area)
19//! - **Modal** - modal dialog webview (blocks interaction)
20//! - **Widget** - small embedded webview (e.g., diff viewer)
21//!
22//! ## Lifecycle
23//!
24//! 1. `CreateWebviewPanel` - build Tauri `WebviewWindow`, set up event
25//! handlers, record in `ApplicationState.Feature.Webviews`.
26//! 2. `SetWebviewHTML` / `SetWebviewOptions` - configure content and title.
27//! 3. `RevealWebviewPanel` - show and focus.
28//! 4. `PostMessageToWebview` - bidirectional IPC between host and webview.
29//! 5. `DisposeWebviewPanel` - close window and clean up state.
30//!
31//! ## Security
32//!
33//! Webview runs in a sandboxed process (no Node.js). All `postMessage` calls
34//! are validated; origins are checked to prevent XSS.
35//! Memory footprint is ~50-100 MB per webview - reuse panels when possible.
36//!
37//! ## VS Code reference
38//!
39//! - `vs/workbench/contrib/webview/browser/webviewService.ts`
40//! - `vs/workbench/api/browser/mainThreadWebview.ts`
41
42use std::collections::HashMap;
43
44use CommonLibrary::{Error::CommonError::CommonError, Webview::WebviewProvider::WebviewProvider};
45use async_trait::async_trait;
46use serde_json::Value;
47
48use super::MountainEnvironment::MountainEnvironment;
49
50// Atomic public DTOs (one export per file).
51pub mod WebviewLifecycleState;
52
53pub mod WebviewMessage;
54
55// Private submodules - implementation only, accessed through the
56// trait impl below.
57#[path = "WebviewProvider/Configuration.rs"]
58mod Configuration;
59
60#[path = "WebviewProvider/Lifecycle.rs"]
61mod Lifecycle;
62
63#[path = "WebviewProvider/Messaging.rs"]
64mod Messaging;
65
66// TODO: content caching for faster reloads, theming (dark/light auto),
67// custom protocols, screenshot/thumbnail generation, performance monitoring
68// (CPU/memory), webview clustering, state snapshots for debugging,
69// accessibility audit, pause-when-hidden, resource preloading, telemetry,
70// offline mode (service workers), session migration, debugging tools.
71
72/// Webview message handler context. Private - only the dispatch
73/// machinery in `Messaging.rs` consumes it.
74#[allow(dead_code)]
75struct WebviewMessageContext {
76 Handle:String,
77
78 SideCarIdentifier:Option<String>,
79
80 PendingResponses:HashMap<String, tokio::sync::oneshot::Sender<Value>>,
81}
82
83#[async_trait]
84impl WebviewProvider for MountainEnvironment {
85 /// Creates a new Webview panel with proper security isolation.
86 async fn CreateWebviewPanel(
87 &self,
88
89 extension_data_value:Value,
90
91 view_type:String,
92
93 title:String,
94
95 _show_options_value:Value,
96
97 panel_options_value:Value,
98
99 content_options_value:Value,
100 ) -> Result<String, CommonError> {
101 Lifecycle::create_webview_panel_impl(
102 self,
103 extension_data_value,
104 view_type,
105 title,
106 _show_options_value,
107 panel_options_value,
108 content_options_value,
109 )
110 .await
111 }
112
113 /// Disposes a Webview panel and cleans up all associated resources.
114 async fn DisposeWebviewPanel(&self, handle:String) -> Result<(), CommonError> {
115 Lifecycle::dispose_webview_panel_impl(self, handle).await
116 }
117
118 /// Reveals (shows and focuses) a Webview panel.
119 async fn RevealWebviewPanel(&self, handle:String, _show_options_value:Value) -> Result<(), CommonError> {
120 Lifecycle::reveal_webview_panel_impl(self, handle, _show_options_value).await
121 }
122
123 /// Sets Webview options (title, icon, etc.).
124 async fn SetWebviewOptions(&self, handle:String, options_value:Value) -> Result<(), CommonError> {
125 Configuration::set_webview_options_impl(self, handle, options_value).await
126 }
127
128 /// Sets the HTML content of a Webview.
129 async fn SetWebviewHTML(&self, handle:String, html:String) -> Result<(), CommonError> {
130 Configuration::set_webview_html_impl(self, handle, html).await
131 }
132
133 /// Posts a message to a Webview with proper error handling.
134 async fn PostMessageToWebview(&self, handle:String, message:Value) -> Result<bool, CommonError> {
135 Messaging::post_message_to_webview_impl(self, handle, message).await
136 }
137}