#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HostScope {
All,
Scheme,
Scoped,
Unknown,
}
pub fn is_host_access_pattern(token: &str) -> bool {
if token == "<all_urls>" {
return true;
}
token.contains("://")
}
pub fn classify_host_pattern(token: &str) -> HostScope {
if token == "<all_urls>" {
return HostScope::All;
}
let Some((scheme, rest)) = token.split_once("://") else {
return HostScope::Unknown;
};
let scheme_is_wildcard = scheme == "*";
let host = match rest.split_once('/') {
Some((h, _)) => h,
None => rest,
};
if host == "*" || host.is_empty() {
return if scheme_is_wildcard {
HostScope::All
} else {
HostScope::Scheme
};
}
if host.starts_with("*.") && host.len() > 2 {
return HostScope::Scoped;
}
if !host.is_empty() {
return HostScope::Scoped;
}
HostScope::Unknown
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn recognizes_blanket_patterns() {
assert_eq!(classify_host_pattern("<all_urls>"), HostScope::All);
assert_eq!(classify_host_pattern("*://*/*"), HostScope::All);
assert_eq!(classify_host_pattern("https://*/*"), HostScope::Scheme);
assert_eq!(classify_host_pattern("http://*/*"), HostScope::Scheme);
assert_eq!(classify_host_pattern("file:///*"), HostScope::Scheme);
}
#[test]
fn recognizes_scoped_patterns() {
assert_eq!(classify_host_pattern("https://*.example.com/*"), HostScope::Scoped);
assert_eq!(classify_host_pattern("*://mail.example.com/*"), HostScope::Scoped);
assert_eq!(
classify_host_pattern("https://example.com/path/*"),
HostScope::Scoped
);
}
#[test]
fn non_patterns_are_unknown() {
assert_eq!(classify_host_pattern("tabs"), HostScope::Unknown);
assert_eq!(classify_host_pattern("cookies"), HostScope::Unknown);
assert_eq!(classify_host_pattern(""), HostScope::Unknown);
}
#[test]
fn detector_agrees_with_classifier() {
for tok in [
"https://*.example.com/*",
"*://*/*",
"<all_urls>",
"file:///*",
] {
assert!(is_host_access_pattern(tok), "{tok} should be a pattern");
}
for tok in ["tabs", "cookies", "activeTab", ""] {
assert!(!is_host_access_pattern(tok), "{tok:?} should not be a pattern");
}
}
}