script/dom/globalscope/
origin.rs1use dom_struct::dom_struct;
6use js::context::JSContext;
7use js::rust::{HandleObject, HandleValue};
8use net_traits::pub_domains::is_same_site;
9use script_bindings::reflector::{Reflector, reflect_dom_object_with_proto};
10use servo_url::{ImmutableOrigin, ServoUrl};
11
12use crate::dom::bindings::codegen::Bindings::OriginBinding::OriginMethods;
13use crate::dom::bindings::conversions::{
14 ConversionResult, FromJSValConvertible, StringificationBehavior, root_from_handlevalue,
15};
16use crate::dom::bindings::error::{Error, Fallible};
17use crate::dom::bindings::root::DomRoot;
18use crate::dom::bindings::str::DOMString;
19use crate::dom::globalscope::GlobalScope;
20use crate::dom::html::htmlanchorelement::HTMLAnchorElement;
21use crate::dom::html::htmlareaelement::HTMLAreaElement;
22use crate::dom::html::links::htmlhyperlinkelementutils::{
23 HyperlinkElement, HyperlinkElementTraits,
24};
25use crate::dom::url::URL;
26use crate::dom::window::Window;
27
28#[dom_struct]
30pub(crate) struct Origin {
31 reflector: Reflector,
32 #[no_trace]
33 origin: ImmutableOrigin,
34}
35
36impl Origin {
37 fn new_inherited(origin: ImmutableOrigin) -> Origin {
38 Origin {
39 reflector: Reflector::new(),
40 origin,
41 }
42 }
43
44 fn new(
45 cx: &mut JSContext,
46 global: &GlobalScope,
47 proto: Option<HandleObject>,
48 origin: ImmutableOrigin,
49 ) -> DomRoot<Origin> {
50 reflect_dom_object_with_proto(cx, Box::new(Origin::new_inherited(origin)), global, proto)
51 }
52
53 fn extract_an_origin_from_platform_object(
55 cx: &mut JSContext,
56 value: HandleValue,
57 current_global: &GlobalScope,
58 ) -> Option<ImmutableOrigin> {
59 if let Ok(origin_obj) = root_from_handlevalue::<Origin>(cx, value) {
61 return Some(origin_obj.origin.clone());
62 }
63
64 if let Ok(url_obj) = root_from_handlevalue::<URL>(cx, value) {
66 return Some(url_obj.origin());
67 }
68
69 if let Ok(window_obj) = root_from_handlevalue::<Window>(cx, value) {
71 let window_origin = window_obj.origin();
72 if !current_global.origin().same_origin_domain(&window_origin) {
73 return None;
74 }
75 return Some(window_origin.immutable().clone());
76 }
77
78 if let Ok(anchor_obj) = root_from_handlevalue::<HTMLAnchorElement>(cx, value) {
80 anchor_obj.reinitialize_url(cx.no_gc());
81 if let Some(ref url) = *anchor_obj.get_url().borrow() {
82 return Some(url.origin());
83 }
84 return None;
85 }
86
87 if let Ok(area_obj) = root_from_handlevalue::<HTMLAreaElement>(cx, value) {
89 area_obj.reinitialize_url(cx.no_gc());
90 if let Some(ref url) = *area_obj.get_url().borrow() {
91 return Some(url.origin());
92 }
93 return None;
94 }
95
96 None
97 }
98}
99
100impl OriginMethods<crate::DomTypeHolder> for Origin {
101 fn Constructor(
103 cx: &mut JSContext,
104 global: &GlobalScope,
105 proto: Option<HandleObject>,
106 ) -> DomRoot<Origin> {
107 Origin::new(cx, global, proto, ImmutableOrigin::new_opaque())
108 }
109
110 fn From(
112 cx: &mut JSContext,
113 global: &GlobalScope,
114 value: HandleValue,
115 ) -> Fallible<DomRoot<Origin>> {
116 if let Some(origin) = Origin::extract_an_origin_from_platform_object(cx, value, global) {
120 return Ok(Origin::new(cx, global, None, origin));
121 }
122
123 if value.get().is_string() {
125 let s = match DOMString::from_jsval(cx, value, StringificationBehavior::Default) {
126 Ok(ConversionResult::Success(s)) => s,
127 _ => return Err(Error::Type(c"Failed to convert value to string".to_owned())),
128 };
129
130 match ServoUrl::parse(&s.str()) {
134 Ok(url) => return Ok(Origin::new(cx, global, None, url.origin())),
135 Err(_) => return Err(Error::Type(c"Failed to parse URL".to_owned())),
136 }
137 }
138
139 Err(Error::Type(
141 c"Value must be a string or a platform object with an origin".to_owned(),
142 ))
143 }
144
145 fn Opaque(&self) -> bool {
147 !self.origin.is_tuple()
148 }
149
150 fn IsSameOrigin(&self, other: &Origin) -> bool {
152 self.origin == other.origin
153 }
154
155 fn IsSameSite(&self, other: &Origin) -> bool {
157 is_same_site(&self.origin, &other.origin)
158 }
159}