Skip to main content

lingxia_webview/
lib.rs

1//! Cross-platform WebView hosting layer for LingXia.
2//!
3//! This crate is strictly *generic* webview hosting: webview creation and
4//! lifecycle, navigation/scheme/event plumbing, and minimal native surface
5//! ownership required by each platform WebView runtime. It contains no
6//! product UI.
7//!
8//! On Windows, host-window grouping, chrome, panels, and app layout live in
9//! `lingxia-windows-sdk`; this crate only provides the WebView2 surface.
10
11use thiserror::Error;
12
13#[cfg(any(all(target_os = "linux", target_env = "ohos"), test))]
14mod bridge_payload;
15
16/// WebView-specific error types
17#[derive(Error, Debug, Clone, PartialEq, Eq)]
18pub enum WebViewError {
19    #[error("WebView error: {0}")]
20    WebView(String),
21
22    #[error("Invalid WebView create options: {0}")]
23    InvalidCreateOptions(String),
24
25    /// The named operation is not available on this platform's WebView runtime.
26    #[error("{0} is not supported on this platform")]
27    Unsupported(String),
28}
29
30#[derive(Error, Debug, Clone, PartialEq, Eq)]
31pub enum WebViewScriptError {
32    #[error("JavaScript error: {0}")]
33    Js(String),
34
35    #[error("JavaScript evaluation timed out")]
36    Timeout,
37
38    #[error("JavaScript evaluation unsupported: {0}")]
39    Unsupported(&'static str),
40
41    #[error("WebView destroyed during JavaScript evaluation")]
42    Destroyed,
43
44    #[error("Navigation changed during JavaScript evaluation")]
45    NavigationChanged,
46
47    #[error("Platform JavaScript evaluation error: {0}")]
48    Platform(String),
49}
50
51#[derive(Error, Debug, Clone, PartialEq, Eq)]
52pub enum WebViewInputError {
53    #[error(transparent)]
54    Script(#[from] WebViewScriptError),
55
56    #[error("Element not found: {0}")]
57    ElementNotFound(String),
58
59    #[error("Element not interactable: {0}")]
60    ElementNotInteractable(String),
61
62    #[error("Input unsupported: {0}")]
63    Unsupported(&'static str),
64
65    #[error("WebView destroyed during input handling")]
66    Destroyed,
67
68    #[error("Navigation changed during input handling")]
69    NavigationChanged,
70
71    #[error("Platform input error: {0}")]
72    Platform(String),
73}
74
75/// Log levels for WebView logging
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77pub enum LogLevel {
78    Verbose,
79    Debug,
80    Info,
81    Warn,
82    Error,
83}
84
85mod error_page;
86/// Typed delegate events: correlated navigation lifecycle, observable state
87/// snapshots, and the canonical derived-state folds.
88pub mod events;
89mod input_helper;
90mod traits;
91/// Process-local URL callback channels for navigation handoff.
92pub mod url_callback;
93mod webview;
94
95#[cfg(target_os = "android")]
96mod android;
97
98#[cfg(any(target_os = "ios", target_os = "macos"))]
99mod apple;
100
101#[cfg(all(target_os = "linux", target_env = "ohos"))]
102mod harmony;
103
104#[cfg(target_os = "windows")]
105mod windows;
106
107// Public exports
108// WebViewError and LogLevel are defined above
109pub use error_page::{LoadErrorPage, render_load_error_page};
110pub use events::{
111    NavigationCancellationReason, NavigationEvent, NavigationId, NavigationOutcome,
112    NavigationProgress, ObservedWebViewState, WebViewEventObserver, WebViewObservedEvent,
113    WebViewStateChange,
114};
115pub use traits::{
116    ClearSiteDataOptions, ClearSiteDataResult, ClickOptions, DownloadRequest, FileChooserFile,
117    FileChooserRequest, FileChooserResponse, FillOptions, LoadDataRequest, LoadError,
118    LoadErrorKind, NavigationPolicy, NavigationRequest, NetworkBody, NetworkCaptureSnapshot,
119    NetworkEntry, NewWindowPolicy, PressOptions, SchemeOutcome, ScrollOptions, SystemPipeReader,
120    TypeOptions, UserAgentOverride, WebResourceBody, WebResourceResponse, WebViewController,
121    WebViewCookie, WebViewCookieSameSite, WebViewCookieSetRequest, WebViewDelegate,
122    WebViewInputController,
123};
124pub use webview::{
125    BrowserWebViewBuilder, ProxyActivation, ProxyApplyReport, ProxyApplyStatus, ProxyConfig,
126    StrictWebViewBuilder, WebTag, WebView, WebViewBuilder, WebViewCreateStage, WebViewDataMode,
127    WebViewEvent, WebViewEventSubscription, WebViewSession,
128};
129
130/// Global website-data operations for privacy surfaces: usage counts,
131/// clear cache, clear cookies & site data.
132///
133/// Every operation here is profile-wide: all browser tabs share one browser
134/// profile (the platform's default data store), so clears affect every site,
135/// not just the current tab. On Windows, [`cache_site_count`] returns `Ok(0)`
136/// because WebView2 cannot enumerate HTTP-cache origins (clearing still
137/// works). Unsupported platforms return [`WebViewError::Unsupported`].
138pub mod data_store {
139    /// Profile-wide cookies/site-data footprint.
140    #[derive(Debug, Clone, Copy)]
141    pub struct SiteDataUsage {
142        /// Sites storing cookies or other site data.
143        pub sites: usize,
144        /// Total cookie count across all sites.
145        pub cookies: usize,
146    }
147
148    #[cfg(any(target_os = "ios", target_os = "macos"))]
149    pub use crate::apple::data_store::{
150        cache_site_count, clear_all_site_data, clear_cache, site_data_usage,
151    };
152
153    #[cfg(target_os = "windows")]
154    pub use crate::windows::data_store::{
155        cache_site_count, clear_all_site_data, clear_cache, site_data_usage,
156    };
157
158    #[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "windows")))]
159    mod unsupported {
160        use super::SiteDataUsage;
161        use crate::WebViewError;
162
163        fn err(action: &str) -> WebViewError {
164            WebViewError::Unsupported(action.to_string())
165        }
166
167        pub async fn cache_site_count() -> Result<usize, WebViewError> {
168            Err(err("cache usage query"))
169        }
170
171        pub async fn site_data_usage() -> Result<SiteDataUsage, WebViewError> {
172            Err(err("site data usage query"))
173        }
174
175        pub async fn clear_cache(_since_unix_ms: Option<u64>) -> Result<(), WebViewError> {
176            Err(err("clear cache"))
177        }
178
179        pub async fn clear_all_site_data(_since_unix_ms: Option<u64>) -> Result<(), WebViewError> {
180            Err(err("clear cookies & site data"))
181        }
182    }
183    #[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "windows")))]
184    pub use unsupported::*;
185}
186
187/// Runtime-scoped APIs (instance lookup/destruction, proxy state).
188pub mod runtime {
189    use std::sync::Arc;
190
191    use crate::webview;
192    use crate::{ProxyApplyReport, ProxyConfig, WebTag, WebView, WebViewError};
193
194    pub fn find_webview(webtag: &WebTag) -> Option<Arc<WebView>> {
195        webview::find_webview(webtag)
196    }
197
198    pub fn list_webviews() -> Vec<WebTag> {
199        webview::list_webviews()
200    }
201
202    pub fn destroy_webview(webtag: &WebTag) {
203        webview::destroy_webview(webtag);
204    }
205
206    pub fn destroy_webview_if_matches(webtag: &WebTag, expected: &Arc<WebView>) -> bool {
207        webview::destroy_webview_if_matches(webtag, expected)
208    }
209
210    pub fn configure_proxy_for_new_webviews(
211        config: Option<ProxyConfig>,
212    ) -> Result<(), WebViewError> {
213        webview::configure_proxy_for_new_webviews(config)
214    }
215
216    pub fn apply_proxy_to_current_runtime(
217        config: Option<ProxyConfig>,
218    ) -> Result<ProxyApplyReport, WebViewError> {
219        webview::apply_proxy_to_current_runtime(config)
220    }
221
222    pub fn configured_proxy_for_new_webviews() -> Option<ProxyConfig> {
223        webview::configured_proxy_for_new_webviews()
224    }
225}
226
227/// Platform-specific APIs used by SDK/FFI integration layers.
228pub mod platform {
229    #[cfg(target_os = "android")]
230    pub mod android {
231        pub use crate::android::{initialize_jni, with_env};
232    }
233
234    #[cfg(any(target_os = "ios", target_os = "macos"))]
235    pub mod apple {
236        #[cfg(target_os = "macos")]
237        pub use crate::apple::toggle_webview_devtools_by_swift_ptr;
238        pub use crate::apple::{
239            BRIDGE_DOWNSTREAM_CSP_SOURCE, BRIDGE_DOWNSTREAM_URL,
240            configure_user_agent_override_for_webviews,
241        };
242    }
243
244    #[cfg(all(target_os = "linux", target_env = "ohos"))]
245    pub mod harmony {
246        pub use crate::harmony::{
247            check_navigation_policy, complete_pending_screenshot_request, notify_webview_state,
248            on_file_chooser_requested, schemehandler::register_custom_schemes, tsfn,
249            webview_controller_created, webview_controller_destroyed,
250        };
251
252        #[doc(hidden)]
253        pub fn on_load_error(webtag: &str, url: &str, error_code: i32, description: &str) {
254            crate::harmony::on_load_error(webtag, url, error_code, description);
255        }
256
257        #[doc(hidden)]
258        pub fn on_download_start(
259            webtag_str: &str,
260            url: &str,
261            user_agent: &str,
262            content_disposition: &str,
263            mime_type: &str,
264            content_length: i64,
265        ) -> bool {
266            crate::harmony::on_download_start(
267                webtag_str,
268                url,
269                user_agent,
270                content_disposition,
271                mime_type,
272                content_length,
273            )
274        }
275    }
276
277    #[cfg(target_os = "windows")]
278    pub mod windows {
279        pub use crate::windows::{
280            WindowsBrowserEmulationProfile, WindowsPreferredColorScheme, WindowsWebViewHandler,
281            WindowsWebViewNativeView, WindowsWebViewNativeViewHost,
282            clear_windows_lxapp_preferred_color_scheme, find_webview_handler,
283            set_webview_composition_hosting, set_webview_devtools_enabled,
284            set_webview_native_view_host, set_webview_user_data_dir,
285            set_windows_browser_emulation_profile_for_new_webviews,
286            set_windows_context_menu_refresh_provider, set_windows_lxapp_preferred_color_scheme,
287            set_windows_preferred_color_scheme_for_new_webviews,
288            webview_composition_hosting_enabled,
289        };
290    }
291}