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