orinium_browser/engine/
origin.rs1use url::{Origin as UrlOrigin, Url};
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
25pub struct Origin {
26 inner: UrlOrigin,
27 is_internal: bool,
28}
29
30impl Origin {
31 pub fn from_url(url: &Url) -> Self {
37 Self {
38 inner: url.origin(),
39 is_internal: false,
40 }
41 }
42
43 pub fn from_url_string(url: &str) -> Self {
46 match Url::parse(url) {
47 Ok(url) => Self::from_url(&url),
48 Err(_) => Self::opaque(),
49 }
50 }
51
52 pub fn internal() -> Self {
54 Self {
55 inner: UrlOrigin::new_opaque(),
56 is_internal: true,
57 }
58 }
59
60 pub fn opaque() -> Self {
62 Self {
63 inner: UrlOrigin::new_opaque(),
64 is_internal: false,
65 }
66 }
67
68 pub fn ascii_serialization(&self) -> String {
70 self.inner.ascii_serialization()
71 }
72
73 pub fn is_network(&self) -> bool {
75 self.inner.is_tuple()
76 }
77
78 pub fn is_opaque(&self) -> bool {
80 !self.inner.is_tuple()
81 }
82
83 pub fn is_internal(&self) -> bool {
85 self.is_internal
86 }
87
88 pub fn same_origin(&self, other: &Self) -> bool {
90 self.inner == other.inner
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97 use crate::test_support::parse_url as url;
98
99 #[test]
100 fn network_origins_equal_with_default_port_normalization() {
101 let a = Origin::from_url(&url("https://example.test/path"));
102 let b = Origin::from_url(&url("https://example.test:443/other"));
103 assert_eq!(a, b);
104 assert!(a.same_origin(&b));
105 assert_eq!(a.ascii_serialization(), "https://example.test");
106 }
107
108 #[test]
109 fn non_default_ports_make_distinct_origins() {
110 let a = Origin::from_url(&url("https://example.test:443/"));
111 let b = Origin::from_url(&url("https://example.test:8443/"));
112 assert!(a.is_network());
113 assert!(b.is_network());
114 assert!(!a.same_origin(&b));
115 assert_eq!(b.ascii_serialization(), "https://example.test:8443");
116 }
117
118 #[test]
119 fn scheme_and_host_differences_break_origin_equality() {
120 let https = Origin::from_url(&url("https://example.test/"));
121 let http = Origin::from_url(&url("http://example.test/"));
122 let other_host = Origin::from_url(&url("https://other.test/"));
123 assert!(!https.same_origin(&http));
124 assert!(!https.same_origin(&other_host));
125 }
126
127 #[test]
128 fn internal_schemes_are_opaque_and_serialize_as_null() {
129 for raw in [
130 "resource:///devtools/index.html",
131 "data:text/plain,hello",
132 "about:blank",
133 ] {
134 let origin = Origin::from_url(&url(raw));
135 assert!(origin.is_opaque(), "{} should be opaque", raw);
136 assert_eq!(origin.ascii_serialization(), "null");
137 }
138 }
139
140 #[test]
141 fn opaque_origins_never_compare_equal() {
142 let a = Origin::from_url_string("resource:///devtools/index.html");
143 let b = Origin::from_url_string("resource:///devtools/index.html");
144 assert!(!a.same_origin(&b));
145 assert_ne!(a, b);
146 }
147
148 #[test]
149 fn unparsable_url_strings_fall_back_to_opaque() {
150 let origin = Origin::from_url_string("::not a url::");
151 assert!(origin.is_opaque());
152 assert!(!origin.is_internal());
153 assert_eq!(origin.ascii_serialization(), "null");
154 }
155
156 #[test]
157 fn resource_url_is_opaque_but_not_internal() {
158 let origin = Origin::from_url(&url("resource:///test/index.html"));
159 assert!(!origin.is_internal());
160 assert!(origin.is_opaque());
161 assert!(!origin.is_network());
162 assert_eq!(origin.ascii_serialization(), "null");
163 }
164
165 #[test]
166 fn data_and_about_urls_are_opaque_but_not_internal() {
167 for raw in ["data:text/plain,hello", "about:blank"] {
168 let origin = Origin::from_url(&url(raw));
169 assert!(origin.is_opaque(), "{} should be opaque", raw);
170 assert!(!origin.is_internal(), "{} should not be internal", raw);
171 assert!(!origin.is_network(), "{} should not be network", raw);
172 }
173 }
174
175 #[test]
176 fn internal_and_opaque_constructors() {
177 let internal = Origin::internal();
178 assert!(internal.is_internal());
179 assert!(internal.is_opaque());
180
181 let opaque = Origin::opaque();
182 assert!(!opaque.is_internal());
183 assert!(opaque.is_opaque());
184 }
185}