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