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::htmlhyperlinkelementutils::{HyperlinkElement, HyperlinkElementTraits};
23use crate::dom::url::URL;
24use crate::dom::window::Window;
25
26#[dom_struct]
28pub(crate) struct Origin {
29 reflector: Reflector,
30 #[no_trace]
31 origin: ImmutableOrigin,
32}
33
34impl Origin {
35 fn new_inherited(origin: ImmutableOrigin) -> Origin {
36 Origin {
37 reflector: Reflector::new(),
38 origin,
39 }
40 }
41
42 fn new(
43 cx: &mut JSContext,
44 global: &GlobalScope,
45 proto: Option<HandleObject>,
46 origin: ImmutableOrigin,
47 ) -> DomRoot<Origin> {
48 reflect_dom_object_with_proto(cx, Box::new(Origin::new_inherited(origin)), global, proto)
49 }
50
51 fn extract_an_origin_from_platform_object(
53 cx: &mut JSContext,
54 value: HandleValue,
55 current_global: &GlobalScope,
56 ) -> Option<ImmutableOrigin> {
57 if let Ok(origin_obj) = root_from_handlevalue::<Origin>(cx, value) {
59 return Some(origin_obj.origin.clone());
60 }
61
62 if let Ok(url_obj) = root_from_handlevalue::<URL>(cx, value) {
64 return Some(url_obj.origin());
65 }
66
67 if let Ok(window_obj) = root_from_handlevalue::<Window>(cx, value) {
69 let window_origin = window_obj.origin();
70 if !current_global.origin().same_origin_domain(&window_origin) {
71 return None;
72 }
73 return Some(window_origin.immutable().clone());
74 }
75
76 if let Ok(anchor_obj) = root_from_handlevalue::<HTMLAnchorElement>(cx, value) {
78 anchor_obj.reinitialize_url();
79 if let Some(ref url) = *anchor_obj.get_url().borrow() {
80 return Some(url.origin());
81 }
82 return None;
83 }
84
85 if let Ok(area_obj) = root_from_handlevalue::<HTMLAreaElement>(cx, value) {
87 area_obj.reinitialize_url();
88 if let Some(ref url) = *area_obj.get_url().borrow() {
89 return Some(url.origin());
90 }
91 return None;
92 }
93
94 None
95 }
96}
97
98impl OriginMethods<crate::DomTypeHolder> for Origin {
99 fn Constructor(
101 cx: &mut JSContext,
102 global: &GlobalScope,
103 proto: Option<HandleObject>,
104 ) -> DomRoot<Origin> {
105 Origin::new(cx, global, proto, ImmutableOrigin::new_opaque())
106 }
107
108 fn From(
110 cx: &mut JSContext,
111 global: &GlobalScope,
112 value: HandleValue,
113 ) -> Fallible<DomRoot<Origin>> {
114 if let Some(origin) = Origin::extract_an_origin_from_platform_object(cx, value, global) {
118 return Ok(Origin::new(cx, global, None, origin));
119 }
120
121 if value.get().is_string() {
123 let s = match DOMString::safe_from_jsval(cx, value, StringificationBehavior::Default) {
124 Ok(ConversionResult::Success(s)) => s,
125 _ => return Err(Error::Type(c"Failed to convert value to string".to_owned())),
126 };
127
128 match ServoUrl::parse(&s.str()) {
132 Ok(url) => return Ok(Origin::new(cx, global, None, url.origin())),
133 Err(_) => return Err(Error::Type(c"Failed to parse URL".to_owned())),
134 }
135 }
136
137 Err(Error::Type(
139 c"Value must be a string or a platform object with an origin".to_owned(),
140 ))
141 }
142
143 fn Opaque(&self) -> bool {
145 !self.origin.is_tuple()
146 }
147
148 fn IsSameOrigin(&self, other: &Origin) -> bool {
150 self.origin == other.origin
151 }
152
153 fn IsSameSite(&self, other: &Origin) -> bool {
155 is_same_site(&self.origin, &other.origin)
156 }
157}