script/dom/closewatcher/
closewatcher.rs1use std::rc::Rc;
6
7use dom_struct::dom_struct;
8use js::context::JSContext;
9use js::gc::HandleObject;
10use script_bindings::cell::DomRefCell;
11use script_bindings::codegen::GenericBindings::WindowBinding::WindowMethods;
12use script_bindings::error::{Error, Fallible};
13use script_bindings::reflector::reflect_dom_object_with_proto;
14use script_bindings::root::DomRoot;
15
16use crate::dom::abortsignal::AbortAlgorithm;
17use crate::dom::bindings::codegen::Bindings::CloseWatcherBinding::{
18 CloseWatcherMethods, CloseWatcherOptions,
19};
20use crate::dom::bindings::codegen::DomTypeHolder::DomTypeHolder;
21use crate::dom::eventtarget::EventTarget;
22use crate::dom::internalclosewatcher::{InternalCloseWatcher, InternalCloseWatcherOwner};
23use crate::dom::window::Window;
24
25#[dom_struct]
26pub(crate) struct CloseWatcher {
27 eventtarget: EventTarget,
28 #[conditional_malloc_size_of]
30 internal_close_watcher: DomRefCell<Option<Rc<InternalCloseWatcher>>>,
31}
32
33impl CloseWatcher {
34 pub(crate) fn new_inherited() -> CloseWatcher {
35 Self {
36 eventtarget: EventTarget::new_inherited(),
37 internal_close_watcher: Default::default(),
38 }
39 }
40
41 pub(crate) fn new_with_proto(
42 cx: &mut JSContext,
43 window: &Window,
44 proto: Option<HandleObject>,
45 ) -> DomRoot<CloseWatcher> {
46 reflect_dom_object_with_proto(cx, Box::new(CloseWatcher::new_inherited()), window, proto)
47 }
48}
49
50impl CloseWatcherMethods<DomTypeHolder> for CloseWatcher {
51 fn Constructor(
53 cx: &mut JSContext,
54 window: &Window,
55 proto: Option<HandleObject>,
56 options: &CloseWatcherOptions,
57 ) -> Fallible<DomRoot<CloseWatcher>> {
58 if !window.Document().is_fully_active() {
61 return Err(Error::InvalidState(Some("Failed to construct 'CloseWatcher': CloseWatchers cannot be created in detached Windows.".into())));
62 }
63 let close_watcher = CloseWatcher::new_with_proto(cx, window, proto);
70 let internal_close_watcher = InternalCloseWatcher::establish(
71 cx.no_gc(),
72 window,
73 &InternalCloseWatcherOwner::CloseWatcher(close_watcher.as_traced()),
74 );
75 if let Some(signal) = options.signal.as_ref() {
77 if signal.aborted() {
79 internal_close_watcher.destroy(cx.no_gc())
80 }
81 signal.add(&AbortAlgorithm::CloseWatcher(
84 internal_close_watcher.clone(),
85 ));
86 }
87 close_watcher
89 .internal_close_watcher
90 .safe_borrow_mut(cx.no_gc())
91 .replace(internal_close_watcher);
92 Ok(close_watcher)
93 }
94
95 fn RequestClose(&self, cx: &mut JSContext) {
97 if let Some(internal) = &*self.internal_close_watcher.borrow() {
100 internal.request_to_close(cx, false);
101 }
102 }
103
104 fn Close(&self, cx: &mut JSContext) {
106 if let Some(internal) = &*self.internal_close_watcher.borrow() {
108 internal.close(cx);
109 }
110 }
111
112 fn Destroy(&self, cx: &mut JSContext) {
114 if let Some(internal) = &*self.internal_close_watcher.borrow() {
116 internal.destroy(cx.no_gc());
117 }
118 }
119
120 event_handler!(cancel, GetOncancel, SetOncancel);
122 event_handler!(close, GetOnclose, SetOnclose);
124}