Mountain/Environment/WebviewProvider.rs
1//! # WebviewProvider (Environment)
2//!
3//! Implements the `WebviewProvider` trait for `MountainEnvironment`, providing
4//! the core logic for creating, managing, and securing Webview panels - the
5//! embedded browser-based UI components that power many extension features.
6//!
7//! ## RESPONSIBILITIES
8//!
9//! ### 1. Webview Panel Creation
10//! - Create webview windows with proper configuration
11//! - Set up webview content (HTML, CSS, JavaScript)
12//! - Configure webview security (CSP, sandbox, permissions)
13//! - Initialize webview lifecycle and event handlers
14//!
15//! ### 2. Webview Management
16//! - Track active webview instances in `ApplicationState.Feature.Webviews`
17//! - Handle webview focus and visibility changes
18//! - Support webview window positioning and sizing
19//! - Manage webview disposal and cleanup
20//!
21//! ### 3. Secure Message Passing
22//! - Establish bidirectional IPC between host and webview
23//! - Validate and route messages between webview and extension sidecar
24//! - Implement message authentication and authorization
25//! - Prevent cross-origin security vulnerabilities
26//!
27//! ### 4. State Persistence
28//! - Save webview state (position, size, content) to `ApplicationState`
29//! - Restore webview state when reopening
30//! - Persist webview settings across sessions
31//! - Handle webview state serialization/deserialization
32//!
33//! ### 5. Content Security
34//! - Enforce content security policy (CSP)
35//! - Sandbox webview content to prevent escape
36//! - Validate webview URLs and origins
37//! - Protect against XSS and injection attacks
38//!
39//! ## ARCHITECTURAL ROLE
40//!
41//! WebviewProvider is the **webview lifecycle manager**:
42//!
43//! ```text
44//! Extension ──► CreateWebview ──► WebviewProvider ──► Tauri WebviewWindow
45//! │ │
46//! └─► IPC ──► Cocoon ◄───────────┘
47//! ```
48//!
49//! ### Position in Mountain
50//! - `Environment` module: Web content capability provider
51//! - Implements `CommonLibrary::Webview::WebviewProvider` trait
52//! - Accessible via `Environment.Require<dyn WebviewProvider>()`
53//!
54//! ### Webview Types
55//! - **Panel**: Sidebar or panel webview (non-floating)
56//! - **Editor**: Webview as custom editor (full editor area)
57//! - **Modal**: Modal dialog webview (centered, blocks interaction)
58//! - **Widget**: Small embedded webview (e.g., diff viewer)
59//!
60//! ### Webview Lifecycle
61//! 1. **Create**: Extension calls `CreateWebview` with options
62//! 2. **Initialize**: Provider builds webview window, sets up event handlers
63//! 3. **Load Content**: HTML loaded, scripts execute
64//! 4. **Ready**: `onDidBecomeVisible` / `onDidBecomeHidden` events
65//! 5. **Dispose**: When closed, cleanup state and resources
66//!
67//! ### Dependencies
68//! - `Tauri`: `WebviewWindowBuilder` for webview creation
69//! - `ApplicationState`: Webview state tracking
70//! - `IPCProvider`: For extension-side communication
71//! - `Log`: Webview lifecycle logging
72//!
73//! ### Dependents
74//! - Extensions: Create webviews via `registerWebviewPanelProvider`
75//! - `Binary::Main`: Webview window creation during startup
76//! - `DispatchLogic::MountainWebviewPostMessageFromGuest`: Webview → host
77//! messages
78//! - UI components: Webview panel management
79//!
80//! ## WEBVIEW OPTIONS
81//!
82//! `WebviewContentOptionsDTO` controls webview behavior:
83//! - `Handle`: Unique UUID for this webview
84//! - `ViewType`: Extension-defined type identifier
85//! - `Title`: Panel title
86//! - `ContentOptions`: HTML, base URL, scripts, styles
87//! - `PanelOptions`: Size, position, enable/disable features
88//! - `SideCarIdentifier`: Host extension sidecar
89//! - `ExtensionIdentifier`: Owning extension ID
90//! - `IsActive`, `IsVisible`: State flags
91//!
92//! ## SECURITY CONSIDERATIONS
93//!
94//! - **Content Security Policy**: Default CSP restricts external resources
95//! - **Sandbox**: Webview runs in sandboxed process (no Node.js)
96//! - **Message Validation**: All postMessage() calls validated
97//! - **Origin Checking**: Verify message source matches expected webview
98//! - **Permission Management**: Granular permissions for APIs (geolocation,
99//! etc.)
100//!
101//! ## MESSAGE FLOW
102//!
103//! 1. Extension → Host: `webview.postMessage({ command: "..." })`
104//! 2. Provider receives via `MountainWebviewPostMessageFromGuest` command
105//! 3. Provider forwards to extension via IPC (`SendNotificationToSideCar`)
106//! 4. Extension processes and responds
107//! 5. Host → Extension: `ipc.postMessage({ command: "..." })`
108//! 6. Extension receives via `onDidReceiveMessage` event
109//!
110//! ## PERFORMANCE
111//!
112//! - Webview creation is relatively expensive (new browser context)
113//! - Reuse webviews when possible instead of creating new ones
114//! - Consider lazy loading for rarely used webviews
115//! - Memory usage: ~50-100MB per webview (depending on content)
116//! - Use `Dispose` promptly when webview no longer needed
117//!
118//! ## ERROR HANDLING
119//!
120//! - Webview creation failure: `CommonError::WebviewCreationFailed`
121//! - IPC communication failure: `CommonError::IPCError`
122//! - Invalid webview options: `CommonError::InvalidArgument`
123//! - Webview already exists: `CommonError::DuplicateWebview`
124//!
125//! ## VS CODE REFERENCE
126//!
127//! Patterns from VS Code:
128//! - `vs/workbench/contrib/webview/browser/webviewService.ts` - Webview service
129//! - `vs/workbench/contrib/webview/common/webview.ts` - Webview data model
130//! - `vs/workbench/api/browser/mainThreadWebview.ts` - Extension API
131//!
132//! ## TODO
133//!
134//! - [ ] Implement webview content caching for faster reloads
135//! - [ ] Add webview theming support (dark/light mode auto)
136//! - [ ] Support webview extensions/plugins (custom protocols)
137//! - [ ] Implement webview screenshot and thumbnail generation
138//! - [ ] Add webview performance monitoring (CPU, memory)
139//! - [ ] Support webview clustering for related views
140//! - [ ] Implement webview state snapshots for debugging
141//! - [ ] Add webview accessibility audit and reporting
142//! - [ ] Support webview pausing (suspend when not visible)
143//! - [ ] Implement webview resource preloading strategies
144//! - [ ] Add webview telemetry for usage and performance
145//! - [ ] Support webview offline mode with service workers
146//! - [ ] Implement webview migration across sessions
147//! - [ ] Add webview debugging tools integration
148//!
149//! ## MODULE STRUCTURE
150//!
151//! - [`lifecycle.rs`](lifecycle.rs) - Webview creation, disposal, reveal
152//! - [`configuration.rs`](configuration.rs) - Options and HTML setting
153//! - [`messaging.rs`](messaging.rs) - Message passing and listeners
154
155use std::collections::HashMap;
156
157use CommonLibrary::{Error::CommonError::CommonError, Webview::WebviewProvider::WebviewProvider};
158use async_trait::async_trait;
159use serde::{Deserialize, Serialize};
160use serde_json::Value;
161
162use super::MountainEnvironment::MountainEnvironment;
163
164/// Represents a Webview message
165#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct WebviewMessage {
167 pub MessageIdentifier:String,
168 pub MessageType:String,
169 pub Payload:Value,
170 pub Source:Option<String>,
171}
172
173/// Webview lifecycle state
174#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
175pub enum WebviewLifecycleState {
176 Unloaded,
177 Loading,
178 Loaded,
179 Visible,
180 Hidden,
181 Disposed,
182}
183
184/// Webview message handler context
185#[allow(dead_code)]
186struct WebviewMessageContext {
187 Handle:String,
188 SideCarIdentifier:Option<String>,
189 PendingResponses:HashMap<String, tokio::sync::oneshot::Sender<Value>>,
190}
191
192// Private submodules containing the actual implementation
193#[path = "WebviewProvider/Lifecycle.rs"]
194mod Lifecycle;
195#[path = "WebviewProvider/Configuration.rs"]
196mod Configuration;
197#[path = "WebviewProvider/Messaging.rs"]
198mod Messaging;
199
200#[async_trait]
201impl WebviewProvider for MountainEnvironment {
202 /// Creates a new Webview panel with proper security isolation.
203 async fn CreateWebviewPanel(
204 &self,
205 extension_data_value:Value,
206 view_type:String,
207 title:String,
208 _show_options_value:Value,
209 panel_options_value:Value,
210 content_options_value:Value,
211 ) -> Result<String, CommonError> {
212 Lifecycle::create_webview_panel_impl(
213 self,
214 extension_data_value,
215 view_type,
216 title,
217 _show_options_value,
218 panel_options_value,
219 content_options_value,
220 )
221 .await
222 }
223
224 /// Disposes a Webview panel and cleans up all associated resources.
225 async fn DisposeWebviewPanel(&self, handle:String) -> Result<(), CommonError> {
226 Lifecycle::dispose_webview_panel_impl(self, handle).await
227 }
228
229 /// Reveals (shows and focuses) a Webview panel.
230 async fn RevealWebviewPanel(&self, handle:String, _show_options_value:Value) -> Result<(), CommonError> {
231 Lifecycle::reveal_webview_panel_impl(self, handle, _show_options_value).await
232 }
233
234 /// Sets Webview options (title, icon, etc.).
235 async fn SetWebviewOptions(&self, handle:String, options_value:Value) -> Result<(), CommonError> {
236 Configuration::set_webview_options_impl(self, handle, options_value).await
237 }
238
239 /// Sets the HTML content of a Webview.
240 async fn SetWebviewHTML(&self, handle:String, html:String) -> Result<(), CommonError> {
241 Configuration::set_webview_html_impl(self, handle, html).await
242 }
243
244 /// Posts a message to a Webview with proper error handling.
245 async fn PostMessageToWebview(&self, handle:String, message:Value) -> Result<bool, CommonError> {
246 Messaging::post_message_to_webview_impl(self, handle, message).await
247 }
248}