use std::cell::Cell;
use dom_struct::dom_struct;
use js::rust::{HandleObject, HandleValue};
use script_traits::BroadcastMsg;
use uuid::Uuid;
use crate::dom::bindings::codegen::Bindings::BroadcastChannelBinding::BroadcastChannelMethods;
use crate::dom::bindings::error::{Error, ErrorResult};
use crate::dom::bindings::reflector::{reflect_dom_object_with_proto, DomObject};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::bindings::structuredclone;
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
#[dom_struct]
pub struct BroadcastChannel {
eventtarget: EventTarget,
name: DOMString,
closed: Cell<bool>,
#[no_trace]
id: Uuid,
}
impl BroadcastChannel {
fn new(
global: &GlobalScope,
proto: Option<HandleObject>,
name: DOMString,
can_gc: CanGc,
) -> DomRoot<BroadcastChannel> {
let channel = reflect_dom_object_with_proto(
Box::new(BroadcastChannel::new_inherited(name)),
global,
proto,
can_gc,
);
global.track_broadcast_channel(&channel);
channel
}
pub fn new_inherited(name: DOMString) -> BroadcastChannel {
BroadcastChannel {
eventtarget: EventTarget::new_inherited(),
name,
closed: Default::default(),
id: Uuid::new_v4(),
}
}
pub fn id(&self) -> &Uuid {
&self.id
}
pub fn closed(&self) -> bool {
self.closed.get()
}
}
impl BroadcastChannelMethods for BroadcastChannel {
fn Constructor(
global: &GlobalScope,
proto: Option<HandleObject>,
can_gc: CanGc,
name: DOMString,
) -> DomRoot<BroadcastChannel> {
BroadcastChannel::new(global, proto, name, can_gc)
}
fn PostMessage(&self, cx: SafeJSContext, message: HandleValue) -> ErrorResult {
if self.closed.get() {
return Err(Error::InvalidState);
}
let data = structuredclone::write(cx, message, None)?;
let global = self.global();
let msg = BroadcastMsg {
origin: global.origin().immutable().clone(),
channel_name: self.Name().to_string(),
data,
};
global.schedule_broadcast(msg, &self.id);
Ok(())
}
fn Name(&self) -> DOMString {
self.name.clone()
}
fn Close(&self) {
self.closed.set(true);
}
event_handler!(messageerror, GetOnmessageerror, SetOnmessageerror);
event_handler!(message, GetOnmessage, SetOnmessage);
}