script/dom/globalscope/
broadcastchannel.rs1use std::cell::Cell;
6
7use dom_struct::dom_struct;
8use js::context::JSContext;
9use js::rust::{HandleObject, HandleValue};
10use script_bindings::domstring::TracedDOMString;
11use script_bindings::reflector::reflect_dom_object_with_proto;
12use servo_constellation_traits::BroadcastChannelMsg;
13use uuid::Uuid;
14
15use crate::dom::bindings::codegen::Bindings::BroadcastChannelBinding::BroadcastChannelMethods;
16use crate::dom::bindings::error::{Error, ErrorResult};
17use crate::dom::bindings::reflector::DomGlobal;
18use crate::dom::bindings::root::DomRoot;
19use crate::dom::bindings::str::DOMString;
20use crate::dom::bindings::structuredclone;
21use crate::dom::eventtarget::EventTarget;
22use crate::dom::globalscope::GlobalScope;
23
24#[dom_struct]
25pub(crate) struct BroadcastChannel {
26 eventtarget: EventTarget,
27 name: TracedDOMString,
28 closed: Cell<bool>,
29 #[no_trace]
30 id: Uuid,
31}
32
33impl BroadcastChannel {
34 fn new(
35 cx: &mut JSContext,
36 global: &GlobalScope,
37 proto: Option<HandleObject>,
38 name: DOMString,
39 ) -> DomRoot<BroadcastChannel> {
40 let channel = reflect_dom_object_with_proto(
41 cx,
42 Box::new(BroadcastChannel::new_inherited(name)),
43 global,
44 proto,
45 );
46 global.track_broadcast_channel(&channel);
47 channel
48 }
49
50 pub(crate) fn new_inherited(name: DOMString) -> BroadcastChannel {
51 BroadcastChannel {
52 eventtarget: EventTarget::new_inherited(),
53 name: name.traced(),
54 closed: Default::default(),
55 id: Uuid::new_v4(),
56 }
57 }
58
59 pub(crate) fn id(&self) -> &Uuid {
62 &self.id
63 }
64
65 pub(crate) fn closed(&self) -> bool {
67 self.closed.get()
68 }
69}
70
71impl BroadcastChannelMethods<crate::DomTypeHolder> for BroadcastChannel {
72 fn Constructor(
74 cx: &mut JSContext,
75 global: &GlobalScope,
76 proto: Option<HandleObject>,
77 name: DOMString,
78 ) -> DomRoot<BroadcastChannel> {
79 BroadcastChannel::new(cx, global, proto, name)
80 }
81
82 fn PostMessage(&self, cx: &mut JSContext, message: HandleValue) -> ErrorResult {
84 if self.closed.get() {
86 return Err(Error::InvalidState(Some(
87 "Cannot post message on a closed BroadcastChannel".to_string(),
88 )));
89 }
90
91 let data = structuredclone::write(cx, message, None)?;
93
94 let global = self.global();
95
96 let msg = BroadcastChannelMsg {
97 origin: global.origin().immutable().clone(),
98 channel_name: String::from(self.Name()),
99 data,
100 };
101
102 global.schedule_broadcast(msg, &self.id);
103 Ok(())
104 }
105
106 fn Name(&self) -> DOMString {
108 self.name.clone().root()
109 }
110
111 fn Close(&self) {
113 self.closed.set(true);
114 }
115
116 event_handler!(messageerror, GetOnmessageerror, SetOnmessageerror);
118
119 event_handler!(message, GetOnmessage, SetOnmessage);
121}