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
//! Turning `tao::event::Event::Opened`'s URLs into a filesystem path.
//!
//! macOS delivers a Finder "Open With → MBR" launch (or a document
//! double-click, once `MBR.app` is the default handler) as this event,
//! wrapping `application(_:open:)` — see `browser::InitialLaunch::Deferred`
//! for the launch-ordering guarantee that makes reacting to it race-free.
//!
//! [`first_local_path`] is pure and carries no `cfg`, even though
//! [`crate::browser`] only ever calls it from `#[cfg(target_os = "macos")]`
//! code — `Event::Opened` is never constructed by tao's Windows or Linux
//! backends, so there is nothing to react to there. Keeping the function
//! itself platform-generic means `cargo test` exercises it on every platform
//! this crate is built on, not only the one it actually fires on.
use std::path::PathBuf;
/// The first URL in `urls` that names a local file, if any.
///
/// `application(_:open:)` is not exclusive to document opens — mbr also
/// registers the `mbr://` URL scheme (see `CFBundleURLTypes` in
/// `macos/MBR.app-template/Contents/Info.plist`), and both arrive through the
/// same event. Anything that is not a `file://` URL is silently skipped
/// rather than treated as an error: there is no other scheme registered
/// today that this code needs to understand, and a future one showing up
/// here should degrade to "no usable path" rather than a hard failure.
///
/// The first match wins: mbr opens one window, so a launch naming several
/// files has to pick one, and "the one Finder listed first" is as good a
/// rule as any.
pub(crate) fn first_local_path(urls: &[url::Url]) -> Option<PathBuf> {
urls.iter().find_map(|url| url.to_file_path().ok())
}
#[cfg(test)]
mod tests {
use super::*;
/// A `file://` URL for `name`, built via `Url::from_file_path` rather
/// than a hardcoded `file:///tmp/...` literal — `to_file_path`'s parsing
/// is platform-specific (Windows requires a drive letter; Unix does not),
/// so a Unix-shaped literal fails to round-trip on Windows and the test
/// itself is what breaks, not the function under test. `from_file_path`
/// and `to_file_path` are each other's inverse on whatever platform the
/// test actually runs on, so this is correct everywhere without `cfg`.
fn file_url(path: &std::path::Path) -> url::Url {
url::Url::from_file_path(path).expect("std::env::temp_dir() is always absolute")
}
#[test]
fn finds_the_first_file_url() {
let path = std::env::temp_dir().join("readme.md");
let urls = vec![
url::Url::parse("https://example.com").unwrap(),
file_url(&path),
];
assert_eq!(first_local_path(&urls), Some(path));
}
#[test]
fn ignores_non_file_urls() {
let urls = vec![
url::Url::parse("https://example.com").unwrap(),
url::Url::parse("mbr://some/deep-link").unwrap(),
];
assert_eq!(first_local_path(&urls), None);
}
#[test]
fn empty_urls_returns_none() {
assert_eq!(first_local_path(&[]), None);
}
#[test]
fn picks_the_first_of_several_file_urls() {
let a = std::env::temp_dir().join("a.md");
let b = std::env::temp_dir().join("b.md");
let urls = vec![file_url(&a), file_url(&b)];
assert_eq!(first_local_path(&urls), Some(a));
}
}