script/dom/
dissimilaroriginwindow.rs1use base::id::PipelineId;
6use constellation_traits::{ScriptToConstellationMessage, StructuredSerializedData};
7use dom_struct::dom_struct;
8use js::jsapi::{Heap, JSObject};
9use js::jsval::UndefinedValue;
10use js::rust::{CustomAutoRooter, CustomAutoRooterGuard, HandleValue, MutableHandleValue};
11use servo_url::ServoUrl;
12
13use crate::dom::bindings::codegen::Bindings::DissimilarOriginWindowBinding;
14use crate::dom::bindings::codegen::Bindings::DissimilarOriginWindowBinding::DissimilarOriginWindowMethods;
15use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowPostMessageOptions;
16use crate::dom::bindings::error::{Error, ErrorResult};
17use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
18use crate::dom::bindings::str::USVString;
19use crate::dom::bindings::structuredclone;
20use crate::dom::bindings::trace::RootedTraceableBox;
21use crate::dom::dissimilaroriginlocation::DissimilarOriginLocation;
22use crate::dom::globalscope::GlobalScope;
23use crate::dom::windowproxy::WindowProxy;
24use crate::script_runtime::{CanGc, JSContext};
25
26#[dom_struct]
36pub(crate) struct DissimilarOriginWindow {
37 globalscope: GlobalScope,
39
40 window_proxy: Dom<WindowProxy>,
42
43 location: MutNullableDom<DissimilarOriginLocation>,
45}
46
47impl DissimilarOriginWindow {
48 pub(crate) fn new(
49 global_to_clone_from: &GlobalScope,
50 window_proxy: &WindowProxy,
51 ) -> DomRoot<Self> {
52 let cx = GlobalScope::get_cx();
53 let win = Box::new(Self {
54 globalscope: GlobalScope::new_inherited(
55 PipelineId::new(),
56 global_to_clone_from.devtools_chan().cloned(),
57 global_to_clone_from.mem_profiler_chan().clone(),
58 global_to_clone_from.time_profiler_chan().clone(),
59 global_to_clone_from.script_to_constellation_chan().clone(),
60 global_to_clone_from.script_to_embedder_chan().clone(),
61 global_to_clone_from.resource_threads().clone(),
62 global_to_clone_from.storage_threads().clone(),
63 global_to_clone_from.origin().clone(),
64 global_to_clone_from.creation_url().clone(),
65 global_to_clone_from.top_level_creation_url().clone(),
66 #[cfg(feature = "webgpu")]
67 global_to_clone_from.wgpu_id_hub(),
68 Some(global_to_clone_from.is_secure_context()),
69 false,
70 global_to_clone_from.font_context().cloned(),
71 ),
72 window_proxy: Dom::from_ref(window_proxy),
73 location: Default::default(),
74 });
75 DissimilarOriginWindowBinding::Wrap::<crate::DomTypeHolder>(cx, win)
76 }
77
78 pub(crate) fn window_proxy(&self) -> DomRoot<WindowProxy> {
79 DomRoot::from_ref(&*self.window_proxy)
80 }
81}
82
83impl DissimilarOriginWindowMethods<crate::DomTypeHolder> for DissimilarOriginWindow {
84 fn Window(&self) -> DomRoot<WindowProxy> {
86 self.window_proxy()
87 }
88
89 fn Self_(&self) -> DomRoot<WindowProxy> {
91 self.window_proxy()
92 }
93
94 fn Frames(&self) -> DomRoot<WindowProxy> {
96 self.window_proxy()
97 }
98
99 fn GetParent(&self) -> Option<DomRoot<WindowProxy>> {
101 if self.window_proxy.is_browsing_context_discarded() {
103 return None;
104 }
105 if let Some(parent) = self.window_proxy.parent() {
107 return Some(DomRoot::from_ref(parent));
108 }
109 Some(DomRoot::from_ref(&*self.window_proxy))
111 }
112
113 fn GetTop(&self) -> Option<DomRoot<WindowProxy>> {
115 if self.window_proxy.is_browsing_context_discarded() {
117 return None;
118 }
119 Some(DomRoot::from_ref(self.window_proxy.top()))
121 }
122
123 fn Length(&self) -> u32 {
125 0
127 }
128
129 fn Close(&self) {
131 }
133
134 fn Closed(&self) -> bool {
136 false
138 }
139
140 fn PostMessage(
142 &self,
143 cx: JSContext,
144 message: HandleValue,
145 target_origin: USVString,
146 transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
147 ) -> ErrorResult {
148 self.post_message_impl(&target_origin, cx, message, transfer)
149 }
150
151 fn PostMessage_(
153 &self,
154 cx: JSContext,
155 message: HandleValue,
156 options: RootedTraceableBox<WindowPostMessageOptions>,
157 ) -> ErrorResult {
158 let mut rooted = CustomAutoRooter::new(
159 options
160 .parent
161 .transfer
162 .iter()
163 .map(|js: &RootedTraceableBox<Heap<*mut JSObject>>| js.get())
164 .collect(),
165 );
166 let transfer = CustomAutoRooterGuard::new(*cx, &mut rooted);
167
168 self.post_message_impl(&options.targetOrigin, cx, message, transfer)
169 }
170
171 fn Opener(&self, _: JSContext, mut retval: MutableHandleValue) {
173 retval.set(UndefinedValue());
175 }
176
177 fn SetOpener(&self, _: JSContext, _: HandleValue) {
179 }
181
182 fn Blur(&self) {
184 }
187
188 fn Focus(&self) {
190 self.window_proxy().focus();
191 }
192
193 fn Location(&self, can_gc: CanGc) -> DomRoot<DissimilarOriginLocation> {
195 self.location
196 .or_init(|| DissimilarOriginLocation::new(self, can_gc))
197 }
198}
199
200impl DissimilarOriginWindow {
201 fn post_message_impl(
203 &self,
204 target_origin: &USVString,
205 cx: JSContext,
206 message: HandleValue,
207 transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
208 ) -> ErrorResult {
209 let data = structuredclone::write(cx, message, Some(transfer))?;
211
212 self.post_message(target_origin, data)
213 }
214
215 pub(crate) fn post_message(
217 &self,
218 target_origin: &USVString,
219 data: StructuredSerializedData,
220 ) -> ErrorResult {
221 let target = self.window_proxy.browsing_context_id();
223 let incumbent = match GlobalScope::incumbent() {
225 None => panic!("postMessage called with no incumbent global"),
226 Some(incumbent) => incumbent,
227 };
228
229 let source_origin = incumbent.origin().immutable().clone();
230
231 let target_origin = match target_origin.0[..].as_ref() {
233 "*" => None,
234 "/" => Some(source_origin.clone()),
235 url => match ServoUrl::parse(url) {
236 Ok(url) => Some(url.origin().clone()),
237 Err(_) => return Err(Error::Syntax(None)),
238 },
239 };
240 let msg = ScriptToConstellationMessage::PostMessage {
241 target,
242 source: incumbent.pipeline_id(),
243 source_origin,
244 target_origin,
245 data,
246 };
247 let _ = incumbent.script_to_constellation_chan().send(msg);
249 Ok(())
250 }
251}