orinium_browser/engine/
origin.rs1use url::{Origin as UrlOrigin, Url};
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
22pub struct Origin(UrlOrigin);
23
24impl Origin {
25 pub fn from_url(url: &Url) -> Self {
27 Self(url.origin())
28 }
29
30 pub fn from_url_string(url: &str) -> Self {
33 match Url::parse(url) {
34 Ok(url) => Self::from_url(&url),
35 Err(_) => Self::opaque(),
36 }
37 }
38
39 pub fn opaque() -> Self {
41 Self(UrlOrigin::new_opaque())
42 }
43
44 pub fn ascii_serialization(&self) -> String {
46 self.0.ascii_serialization()
47 }
48
49 pub fn is_network(&self) -> bool {
51 self.0.is_tuple()
52 }
53
54 pub fn is_opaque(&self) -> bool {
56 !self.0.is_tuple()
57 }
58
59 pub fn same_origin(&self, other: &Self) -> bool {
61 self.0 == other.0
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 fn url(s: &str) -> Url {
70 Url::parse(s).unwrap()
71 }
72
73 #[test]
74 fn network_origins_equal_with_default_port_normalization() {
75 let a = Origin::from_url(&url("https://example.test/path"));
76 let b = Origin::from_url(&url("https://example.test:443/other"));
77 assert_eq!(a, b);
78 assert!(a.same_origin(&b));
79 assert_eq!(a.ascii_serialization(), "https://example.test");
80 }
81
82 #[test]
83 fn non_default_ports_make_distinct_origins() {
84 let a = Origin::from_url(&url("https://example.test:443/"));
85 let b = Origin::from_url(&url("https://example.test:8443/"));
86 assert!(a.is_network());
87 assert!(b.is_network());
88 assert!(!a.same_origin(&b));
89 assert_eq!(b.ascii_serialization(), "https://example.test:8443");
90 }
91
92 #[test]
93 fn scheme_and_host_differences_break_origin_equality() {
94 let https = Origin::from_url(&url("https://example.test/"));
95 let http = Origin::from_url(&url("http://example.test/"));
96 let other_host = Origin::from_url(&url("https://other.test/"));
97 assert!(!https.same_origin(&http));
98 assert!(!https.same_origin(&other_host));
99 }
100
101 #[test]
102 fn internal_schemes_are_opaque_and_serialize_as_null() {
103 for raw in [
104 "resource:///devtools/index.html",
105 "data:text/plain,hello",
106 "about:blank",
107 ] {
108 let origin = Origin::from_url(&url(raw));
109 assert!(origin.is_opaque(), "{} should be opaque", raw);
110 assert_eq!(origin.ascii_serialization(), "null");
111 }
112 }
113
114 #[test]
115 fn opaque_origins_never_compare_equal() {
116 let a = Origin::from_url_string("resource:///devtools/index.html");
117 let b = Origin::from_url_string("resource:///devtools/index.html");
118 assert!(!a.same_origin(&b));
119 assert_ne!(a, b);
120 }
121
122 #[test]
123 fn unparsable_url_strings_fall_back_to_opaque() {
124 let origin = Origin::from_url_string("::not a url::");
125 assert!(origin.is_opaque());
126 assert_eq!(origin.ascii_serialization(), "null");
127 }
128}