1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! URL opening — cross-platform hand-off to the OS for external
//! links. Used by the `<a href>` click default action (Phase C.2).
//!
//! ## Trait seam
//!
//! Apps plug a concrete [`UrlOpener`] into `App::with_url_opener`.
//! Production uses [`SystemUrlOpener`] (shells out via the `open`
//! crate); tests use [`MemoryUrlOpener`] which records calls
//! without touching the real OS.
//!
//! Mirrors the `Clipboard` trait in
//! `runtime::selection::clipboard` — same "stub the side-effect
//! boundary" pattern, same test ergonomics.
//!
//! ## Scope (v1)
//!
//! The runtime only calls `open` for URLs with an HTML-standard
//! **external** scheme: `http`, `https`, `mailto`, `ftp`, `file`.
//! (Plus `tel`, `sms`, `data`, `blob` — matching MDN's `<a href>`
//! spec. `javascript:` is intentionally excluded for security.)
//! Anything else is treated as internal — routing is the app's
//! job.
use RefCell;
/// Open `url` in the system's default handler. Implementations are
/// interior-mutable so a single `Rc<dyn UrlOpener>` can be shared
/// across the App, its event listeners, and test assertions.
/// Production opener. Wraps the `open` crate which probes for the
/// right platform invocation (`xdg-open` on Linux, `open` on macOS,
/// `start` on Windows). Zero-cost when idle.
;
/// Test opener. Records every URL opened in an internal log,
/// retrievable via [`opened`](Self::opened). Used by app tests
/// so they don't shell out to the user's browser when
/// `<a href>` click defaults fire.
/// Scheme of `url` — the substring before the first colon, or
/// empty when there's no colon (relative path / fragment).
///
/// Not a full RFC 3986 scheme parse — we just need a lowercase
/// token to match against the external allowlist. Case-insensitive:
/// `HTTP://Example.com` → `"http"`.
/// Is `scheme` one the runtime will hand off to the OS?
/// The allowlist matches MDN's `<a href>` scheme list minus
/// `javascript:` (security risk, explicitly excluded).