Skip to main content

lingxia_webview/
error_page.rs

1/// Localized content for the built-in WebView load-error document.
2#[derive(Debug, Clone, Copy)]
3pub struct LoadErrorPage<'a> {
4    pub title: &'a str,
5    pub message: &'a str,
6    pub retry_label: &'a str,
7    pub retry_url: &'a str,
8}
9
10/// Render the one cross-platform load-error document used by managed WebViews
11/// and native URL surfaces.
12pub fn render_load_error_page(content: LoadErrorPage<'_>) -> String {
13    let title = html_text(content.title);
14    let message = html_text(content.message);
15    let retry_label = html_text(content.retry_label);
16    let retry_url = html_attribute(content.retry_url);
17    format!(
18        r#"<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="color-scheme" content="light dark"><style>html,body{{height:100%;margin:0}}body{{display:flex;align-items:center;justify-content:center;padding:24px;font-family:system-ui,sans-serif;background:#f7f8fb;color:#1c2233}}main{{max-width:320px;text-align:center}}h1{{font-size:18px;margin:0 0 8px}}p{{font-size:14px;line-height:1.5;color:#70788f;margin:0 0 20px}}button{{border:0;border-radius:10px;padding:11px 28px;background:#2f6bff;color:white;font:600 15px system-ui;cursor:pointer}}@media (prefers-color-scheme:dark){{body{{background:#16181d;color:#e8eaf0}}p{{color:#9aa2b5}}}}</style></head><body><main><h1>{title}</h1><p>{message}</p><button id="retry" data-url="{retry_url}">{retry_label}</button></main><script>const retry=document.getElementById('retry');retry.addEventListener('click',()=>location.replace(retry.dataset.url));</script></body></html>"#
19    )
20}
21
22fn html_text(value: &str) -> String {
23    value
24        .replace('&', "&amp;")
25        .replace('<', "&lt;")
26        .replace('>', "&gt;")
27}
28
29fn html_attribute(value: &str) -> String {
30    html_text(value)
31        .replace('"', "&quot;")
32        .replace('\'', "&#39;")
33}
34
35#[cfg(test)]
36mod tests {
37    use super::*;
38
39    #[test]
40    fn escapes_localized_content_and_retry_url() {
41        let html = render_load_error_page(LoadErrorPage {
42            title: "<offline>",
43            message: "A & B",
44            retry_label: "Retry",
45            retry_url: "https://example.test/?q=\"'><script>",
46        });
47        assert!(html.contains("&lt;offline&gt;"));
48        assert!(html.contains("A &amp; B"));
49        assert!(html.contains("&quot;&#39;&gt;&lt;script&gt;"));
50    }
51}