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 #[allow(unsafe_code)]
49 pub(crate) fn new(
50 global_to_clone_from: &GlobalScope,
51 window_proxy: &WindowProxy,
52 ) -> DomRoot<Self> {
53 let cx = GlobalScope::get_cx();
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().clone(),
66 global_to_clone_from.top_level_creation_url().clone(),
67 global_to_clone_from.microtask_queue().clone(),
70 #[cfg(feature = "webgpu")]
71 global_to_clone_from.wgpu_id_hub(),
72 Some(global_to_clone_from.is_secure_context()),
73 false,
74 global_to_clone_from.font_context().cloned(),
75 ),
76 window_proxy: Dom::from_ref(window_proxy),
77 location: Default::default(),
78 });
79 DissimilarOriginWindowBinding::Wrap::<crate::DomTypeHolder>(cx, win)
80 }
81
82 pub(crate) fn window_proxy(&self) -> DomRoot<WindowProxy> {
83 DomRoot::from_ref(&*self.window_proxy)
84 }
85}
86
87impl DissimilarOriginWindowMethods<crate::DomTypeHolder> for DissimilarOriginWindow {
88 fn Window(&self) -> DomRoot<WindowProxy> {
90 self.window_proxy()
91 }
92
93 fn Self_(&self) -> DomRoot<WindowProxy> {
95 self.window_proxy()
96 }
97
98 fn Frames(&self) -> DomRoot<WindowProxy> {
100 self.window_proxy()
101 }
102
103 fn GetParent(&self) -> Option<DomRoot<WindowProxy>> {
105 if self.window_proxy.is_browsing_context_discarded() {
107 return None;
108 }
109 if let Some(parent) = self.window_proxy.parent() {
111 return Some(DomRoot::from_ref(parent));
112 }
113 Some(DomRoot::from_ref(&*self.window_proxy))
115 }
116
117 fn GetTop(&self) -> Option<DomRoot<WindowProxy>> {
119 if self.window_proxy.is_browsing_context_discarded() {
121 return None;
122 }
123 Some(DomRoot::from_ref(self.window_proxy.top()))
125 }
126
127 fn Length(&self) -> u32 {
129 0
131 }
132
133 fn Close(&self) {
135 }
137
138 fn Closed(&self) -> bool {
140 false
142 }
143
144 fn PostMessage(
146 &self,
147 cx: JSContext,
148 message: HandleValue,
149 target_origin: USVString,
150 transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
151 ) -> ErrorResult {
152 self.post_message_impl(&target_origin, cx, message, transfer)
153 }
154
155 fn PostMessage_(
157 &self,
158 cx: JSContext,
159 message: HandleValue,
160 options: RootedTraceableBox<WindowPostMessageOptions>,
161 ) -> ErrorResult {
162 let mut rooted = CustomAutoRooter::new(
163 options
164 .parent
165 .transfer
166 .iter()
167 .map(|js: &RootedTraceableBox<Heap<*mut JSObject>>| js.get())
168 .collect(),
169 );
170 let transfer = CustomAutoRooterGuard::new(*cx, &mut rooted);
171
172 self.post_message_impl(&options.targetOrigin, cx, message, transfer)
173 }
174
175 fn Opener(&self, _: JSContext, mut retval: MutableHandleValue) {
177 retval.set(UndefinedValue());
179 }
180
181 fn SetOpener(&self, _: JSContext, _: HandleValue) {
183 }
185
186 fn Blur(&self) {
188 }
191
192 fn Focus(&self) {
194 self.window_proxy().focus();
195 }
196
197 fn Location(&self, can_gc: CanGc) -> DomRoot<DissimilarOriginLocation> {
199 self.location
200 .or_init(|| DissimilarOriginLocation::new(self, can_gc))
201 }
202}
203
204impl DissimilarOriginWindow {
205 fn post_message_impl(
207 &self,
208 target_origin: &USVString,
209 cx: JSContext,
210 message: HandleValue,
211 transfer: CustomAutoRooterGuard<Vec<*mut JSObject>>,
212 ) -> ErrorResult {
213 let data = structuredclone::write(cx, message, Some(transfer))?;
215
216 self.post_message(target_origin, data)
217 }
218
219 pub(crate) fn post_message(
221 &self,
222 target_origin: &USVString,
223 data: StructuredSerializedData,
224 ) -> ErrorResult {
225 let target = self.window_proxy.browsing_context_id();
227 let incumbent = match GlobalScope::incumbent() {
229 None => panic!("postMessage called with no incumbent global"),
230 Some(incumbent) => incumbent,
231 };
232
233 let source_origin = incumbent.origin().immutable().clone();
234
235 let target_origin = match target_origin.0[..].as_ref() {
237 "*" => None,
238 "/" => Some(source_origin.clone()),
239 url => match ServoUrl::parse(url) {
240 Ok(url) => Some(url.origin().clone()),
241 Err(_) => return Err(Error::Syntax(None)),
242 },
243 };
244 let msg = ScriptToConstellationMessage::PostMessage {
245 target,
246 source: incumbent.pipeline_id(),
247 source_origin,
248 target_origin,
249 data,
250 };
251 let _ = incumbent.script_to_constellation_chan().send(msg);
253 Ok(())
254 }
255}