Skip to main content

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
155#![allow(non_snake_case)]
156
157use std::collections::HashMap;
158
159use CommonLibrary::{Error::CommonError::CommonError, Webview::WebviewProvider::WebviewProvider};
160use async_trait::async_trait;
161use serde_json::Value;
162
163use super::MountainEnvironment::MountainEnvironment;
164
165// Atomic public DTOs (one export per file).
166pub mod WebviewLifecycleState;
167pub mod WebviewMessage;
168
169// Private submodules - implementation only, accessed through the
170// trait impl below.
171#[path = "WebviewProvider/Configuration.rs"]
172mod Configuration;
173#[path = "WebviewProvider/Lifecycle.rs"]
174mod Lifecycle;
175#[path = "WebviewProvider/Messaging.rs"]
176mod Messaging;
177
178/// Webview message handler context. Private - only the dispatch
179/// machinery in `Messaging.rs` consumes it.
180#[allow(dead_code)]
181struct WebviewMessageContext {
182	Handle:String,
183	SideCarIdentifier:Option<String>,
184	PendingResponses:HashMap<String, tokio::sync::oneshot::Sender<Value>>,
185}
186
187#[async_trait]
188impl WebviewProvider for MountainEnvironment {
189	/// Creates a new Webview panel with proper security isolation.
190	async fn CreateWebviewPanel(
191		&self,
192		extension_data_value:Value,
193		view_type:String,
194		title:String,
195		_show_options_value:Value,
196		panel_options_value:Value,
197		content_options_value:Value,
198	) -> Result<String, CommonError> {
199		Lifecycle::create_webview_panel_impl(
200			self,
201			extension_data_value,
202			view_type,
203			title,
204			_show_options_value,
205			panel_options_value,
206			content_options_value,
207		)
208		.await
209	}
210
211	/// Disposes a Webview panel and cleans up all associated resources.
212	async fn DisposeWebviewPanel(&self, handle:String) -> Result<(), CommonError> {
213		Lifecycle::dispose_webview_panel_impl(self, handle).await
214	}
215
216	/// Reveals (shows and focuses) a Webview panel.
217	async fn RevealWebviewPanel(&self, handle:String, _show_options_value:Value) -> Result<(), CommonError> {
218		Lifecycle::reveal_webview_panel_impl(self, handle, _show_options_value).await
219	}
220
221	/// Sets Webview options (title, icon, etc.).
222	async fn SetWebviewOptions(&self, handle:String, options_value:Value) -> Result<(), CommonError> {
223		Configuration::set_webview_options_impl(self, handle, options_value).await
224	}
225
226	/// Sets the HTML content of a Webview.
227	async fn SetWebviewHTML(&self, handle:String, html:String) -> Result<(), CommonError> {
228		Configuration::set_webview_html_impl(self, handle, html).await
229	}
230
231	/// Posts a message to a Webview with proper error handling.
232	async fn PostMessageToWebview(&self, handle:String, message:Value) -> Result<bool, CommonError> {
233		Messaging::post_message_to_webview_impl(self, handle, message).await
234	}
235}