1mod automation;
2mod chooser;
3mod downloads;
4mod internal_pages;
5mod policy;
6mod tabs;
7mod types;
8mod webview;
9
10pub use lingxia_webview::{
11 NetworkBody, NetworkCaptureSnapshot, NetworkEntry, WebViewCookie, WebViewCookieSameSite,
12 WebViewCookieSetRequest,
13};
14pub use policy::{extract_url_scheme, is_lingxia_startup_url, normalize_url_for_wait_compare};
15use std::sync::Arc;
16use std::time::Duration;
17pub use types::{
18 BrowserAddressAction, BrowserAddressInputContext, BrowserAddressInputError,
19 BrowserAddressInputRequest, BrowserAddressInputResponse, BrowserAddressInputTrigger,
20 BrowserAddressNavigation, BrowserAddressState, BrowserAddressSuggestion,
21 BrowserAddressValueKind, BrowserAutomationError, BrowserElementInfo, BrowserNativeInputHost,
22 BrowserNavigationPolicyDecision, BrowserNavigationPolicyRequest,
23 BrowserNavigationPolicyResponse, BrowserNavigationTarget, BrowserRect, BrowserTabInfo,
24 BrowserWaitCondition, BrowserWaitResult,
25};
26
27pub use lxapp::LxAppError;
28
29pub const BUILTIN_BROWSER_APPID: &str = "app.lingxia.browser";
30pub type BrowserPageMetadataHandler = Arc<dyn Fn(&str, &str) + Send + Sync>;
33
34pub fn classify_navigation(
35 request: BrowserNavigationPolicyRequest,
36) -> BrowserNavigationPolicyResponse {
37 policy::handle_browser_navigation_policy(request)
38}
39
40pub fn classify_navigation_json(request_json: &str) -> Option<String> {
41 policy::handle_browser_navigation_policy_json(request_json)
42}
43
44#[doc(hidden)]
45pub fn set_navigation_finished_handler(handler: BrowserPageMetadataHandler) {
46 tabs::set_navigation_finished_handler(handler);
47}
48
49#[doc(hidden)]
50pub fn set_title_changed_handler(handler: BrowserPageMetadataHandler) {
51 tabs::set_title_changed_handler(handler);
52}
53
54#[doc(hidden)]
55pub fn register_document_script(js: impl Into<String>) {
56 internal_pages::register_browser_document_script(js);
57}
58
59#[doc(hidden)]
60pub fn install_runtime() {
61 lxapp::register_page_resolver(internal_pages::browser_logic_page_path_for_tab_path);
62 lingxia_transfer::runtime::register_browser_tab_path_resolver(tabs::browser_tab_path_for_id);
63 lingxia_transfer::runtime::register_browser_retry_handler(
64 downloads::retry_browser_owned_download,
65 );
66}
67
68#[doc(hidden)]
69pub fn register_internal_page(
70 route: impl Into<String>,
71 entry_asset: impl Into<String>,
72) -> Result<(), LxAppError> {
73 internal_pages::register_browser_internal_page(route, entry_asset)
74}
75
76pub fn open(url: &str, tab_id: Option<&str>) -> Result<String, LxAppError> {
77 tabs::open_internal_browser_tab(url, tab_id)
78}
79
80pub fn open_for_app(
81 appid: &str,
82 session_id: u64,
83 url: &str,
84 tab_id: Option<&str>,
85) -> Result<String, LxAppError> {
86 tabs::open_internal_browser_tab_for_owner(
87 appid,
88 session_id,
89 url,
90 tab_id,
91 false,
92 false,
93 lingxia_webview::WebViewDataMode::ProfileDefault,
94 false,
95 )
96}
97
98pub fn open_aside_for_app(
100 appid: &str,
101 session_id: u64,
102 url: &str,
103 tab_id: Option<&str>,
104) -> Result<String, LxAppError> {
105 tabs::open_internal_browser_tab_for_owner(
106 appid,
107 session_id,
108 url,
109 tab_id,
110 false,
111 true,
112 lingxia_webview::WebViewDataMode::ProfileDefault,
113 false,
114 )
115}
116
117pub fn open_standalone_for_app(
121 appid: &str,
122 session_id: u64,
123 url: &str,
124 tab_id: Option<&str>,
125 data_mode: lingxia_webview::WebViewDataMode,
126 url_callback: bool,
127) -> Result<String, LxAppError> {
128 tabs::open_internal_browser_tab_for_owner(
129 appid,
130 session_id,
131 url,
132 tab_id,
133 true,
134 false,
135 data_mode,
136 url_callback,
137 )
138}
139
140pub fn tab_is_aside(tab_id: &str) -> bool {
142 tabs::is_aside_tab(tab_id)
143}
144
145pub fn tab_is_standalone(tab_id: &str) -> bool {
148 tabs::is_standalone_tab(tab_id)
149}
150
151pub fn close(tab_id: &str) -> Result<(), LxAppError> {
152 tabs::close_browser_tab(tab_id)
153}
154
155pub fn prune_stale_owner_tabs(owner_appid: &str, current_session_id: u64) -> usize {
157 tabs::prune_stale_owner_tabs(owner_appid, current_session_id)
158}
159
160pub fn discard(tab_id: &str) -> Result<(), LxAppError> {
162 tabs::discard_browser_tab(tab_id)
163}
164
165pub fn reactivate(tab_id: &str) -> Result<(), LxAppError> {
167 tabs::reactivate_browser_tab(tab_id)
168}
169
170pub fn mark_active(tab_id: &str) {
172 tabs::mark_browser_tab_active(tab_id)
173}
174
175pub fn clear_active() {
177 tabs::clear_active_browser_tab()
178}
179
180pub fn tabs() -> Vec<BrowserTabInfo> {
181 tabs::browser_tabs()
182}
183
184pub fn current_tab() -> Option<BrowserTabInfo> {
185 tabs::browser_current_tab()
186}
187
188pub fn automation_current_tab() -> Option<BrowserTabInfo> {
191 tabs::browser_automation_current_tab()
192}
193
194pub fn activate(tab_id: &str) -> Result<BrowserTabInfo, BrowserAutomationError> {
195 tabs::browser_activate_tab(tab_id)
196}
197
198pub fn set_tabs_changed_handler(handler: Arc<dyn Fn() + Send + Sync>) {
207 tabs::set_tabs_changed_handler(handler);
208}
209
210pub fn set_tab_present_handler(handler: Arc<dyn Fn(&str) + Send + Sync>) {
216 tabs::set_tab_present_handler(handler);
217}
218
219pub fn present(tab_id: &str) -> Result<BrowserTabInfo, BrowserAutomationError> {
221 tabs::browser_present_tab(tab_id)
222}
223
224pub fn tab_favicon(tab_id: &str) -> Option<Arc<Vec<u8>>> {
229 tabs::browser_tab_favicon(tab_id)
230}
231
232pub fn register_native_input_host(host: Arc<dyn BrowserNativeInputHost>) -> bool {
233 automation::register_native_input_host(host)
234}
235
236pub async fn evaluate_javascript(
237 tab_id: &str,
238 js: &str,
239) -> Result<serde_json::Value, BrowserAutomationError> {
240 automation::browser_evaluate_javascript(tab_id, js).await
241}
242
243pub async fn take_screenshot(tab_id: &str) -> Result<Vec<u8>, BrowserAutomationError> {
244 automation::browser_take_screenshot(tab_id).await
245}
246
247pub async fn current_url(tab_id: &str) -> Result<Option<String>, BrowserAutomationError> {
248 automation::browser_current_url(tab_id).await
249}
250
251pub fn reload(tab_id: &str) -> Result<(), BrowserAutomationError> {
252 automation::browser_reload(tab_id)
253}
254
255pub fn go_back(tab_id: &str) -> Result<(), BrowserAutomationError> {
256 automation::browser_go_back(tab_id)
257}
258
259pub fn go_forward(tab_id: &str) -> Result<(), BrowserAutomationError> {
260 automation::browser_go_forward(tab_id)
261}
262
263pub async fn list_cookies(tab_id: &str) -> Result<Vec<WebViewCookie>, BrowserAutomationError> {
264 automation::browser_list_cookies(tab_id).await
265}
266
267pub async fn list_all_cookies(tab_id: &str) -> Result<Vec<WebViewCookie>, BrowserAutomationError> {
268 automation::browser_list_all_cookies(tab_id).await
269}
270
271pub async fn set_cookie(
272 tab_id: &str,
273 request: WebViewCookieSetRequest,
274) -> Result<(), BrowserAutomationError> {
275 automation::browser_set_cookie(tab_id, request).await
276}
277
278pub async fn delete_cookie(
279 tab_id: &str,
280 name: &str,
281 domain: &str,
282 path: &str,
283) -> Result<(), BrowserAutomationError> {
284 automation::browser_delete_cookie(tab_id, name, domain, path).await
285}
286
287pub async fn clear_cookies(tab_id: &str) -> Result<(), BrowserAutomationError> {
288 automation::browser_clear_cookies(tab_id).await
289}
290
291pub async fn clear_site_data(
292 tab_id: &str,
293 options: lingxia_webview::ClearSiteDataOptions,
294) -> Result<lingxia_webview::ClearSiteDataResult, BrowserAutomationError> {
295 automation::browser_clear_site_data(tab_id, options).await
296}
297
298pub async fn start_network_capture(tab_id: &str) -> Result<(), BrowserAutomationError> {
299 automation::browser_start_network_capture(tab_id).await
300}
301
302pub async fn stop_network_capture(tab_id: &str) -> Result<(), BrowserAutomationError> {
303 automation::browser_stop_network_capture(tab_id).await
304}
305
306pub async fn network_entries(
307 tab_id: &str,
308) -> Result<NetworkCaptureSnapshot, BrowserAutomationError> {
309 automation::browser_network_entries(tab_id).await
310}
311
312pub async fn clear_network_capture(tab_id: &str) -> Result<(), BrowserAutomationError> {
313 automation::browser_clear_network_capture(tab_id).await
314}
315
316pub async fn query(
317 tab_id: &str,
318 selector: &str,
319) -> Result<BrowserElementInfo, BrowserAutomationError> {
320 automation::browser_query(tab_id, selector).await
321}
322
323pub async fn query_with_max_text(
324 tab_id: &str,
325 selector: &str,
326 max_text_chars: Option<usize>,
327) -> Result<BrowserElementInfo, BrowserAutomationError> {
328 automation::browser_query_with_max_text(tab_id, selector, max_text_chars).await
329}
330
331pub async fn wait(
332 tab_id: &str,
333 condition: BrowserWaitCondition,
334 timeout: Duration,
335) -> Result<BrowserWaitResult, BrowserAutomationError> {
336 automation::browser_wait(tab_id, condition, timeout).await
337}
338
339pub async fn wait_for_url(
340 tab_id: &str,
341 url: &str,
342 timeout: Duration,
343) -> Result<BrowserWaitResult, BrowserAutomationError> {
344 automation::browser_wait_for_url(tab_id, url, timeout).await
345}
346
347pub async fn wait_for_url_contains(
348 tab_id: &str,
349 text: &str,
350 timeout: Duration,
351) -> Result<BrowserWaitResult, BrowserAutomationError> {
352 automation::browser_wait_for_url_contains(tab_id, text, timeout).await
353}
354
355pub async fn wait_for_navigation(
356 tab_id: &str,
357 timeout: Duration,
358 wait_until_complete: bool,
359) -> Result<BrowserWaitResult, BrowserAutomationError> {
360 automation::browser_wait_for_navigation(tab_id, timeout, wait_until_complete).await
361}
362
363pub async fn click(tab_id: &str, selector: &str) -> Result<(), BrowserAutomationError> {
364 automation::browser_click(tab_id, selector).await
365}
366
367pub async fn type_text(
368 tab_id: &str,
369 selector: &str,
370 text: &str,
371) -> Result<(), BrowserAutomationError> {
372 automation::browser_type_text(tab_id, selector, text).await
373}
374
375pub async fn fill(tab_id: &str, selector: &str, text: &str) -> Result<(), BrowserAutomationError> {
376 automation::browser_fill(tab_id, selector, text).await
377}
378
379pub async fn press(tab_id: &str, key: &str) -> Result<(), BrowserAutomationError> {
380 automation::browser_press(tab_id, key).await
381}
382
383pub async fn scroll(tab_id: &str, dx: f64, dy: f64) -> Result<(), BrowserAutomationError> {
384 automation::browser_scroll(tab_id, dx, dy).await
385}
386
387pub async fn scroll_to(tab_id: &str, selector: &str) -> Result<(), BrowserAutomationError> {
388 automation::browser_scroll_to(tab_id, selector).await
389}
390
391pub fn tab_path(tab_id: &str) -> String {
392 tabs::browser_tab_path_for_id(tab_id)
393}
394
395pub fn update_tab(tab_id: &str, current_url: Option<&str>, title: Option<&str>) -> bool {
396 tabs::browser_update_tab_info(tab_id, current_url, title)
397}
398
399pub fn start_download(
400 tab_id: &str,
401 url: &str,
402 user_agent: Option<&str>,
403 suggested_filename: Option<&str>,
404 source_page_url: Option<&str>,
405 cookie: Option<&str>,
406) -> Result<(), LxAppError> {
407 downloads::start_native_browser_download(
408 tab_id,
409 url,
410 user_agent,
411 suggested_filename,
412 source_page_url,
413 cookie,
414 )
415}
416
417#[doc(hidden)]
418pub fn register_bundled_app() {
419 tabs::register_builtin_browser_host();
420}
421
422#[doc(hidden)]
423pub fn warmup() {
424 if let Err(err) = internal_pages::warmup_builtin_browser_runtime() {
425 lxapp::warn!("[InternalBrowser] warmup failed: {}", err);
426 }
427}