script/dom/
useractivation.rs1use std::ops::Add;
6
7use dom_struct::dom_struct;
8use js::context::JSContext;
9use script_bindings::codegen::GenericBindings::UserActivationBinding::UserActivationMethods;
10use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
11use servo_base::cross_process_instant::CrossProcessInstant;
12use time::Duration;
13
14use crate::dom::bindings::reflector::DomGlobal;
15use crate::dom::bindings::root::{Dom, DomRoot};
16use crate::dom::document::{
17 Document, SameOriginDescendantNavigablesIterator, SameoriginAncestorNavigablesIterator,
18};
19use crate::dom::globalscope::GlobalScope;
20
21#[dom_struct]
23pub(crate) struct UserActivation {
24 reflector_: Reflector,
25}
26
27impl UserActivation {
28 fn new_inherited() -> UserActivation {
29 UserActivation {
30 reflector_: Reflector::new(),
31 }
32 }
33
34 pub(crate) fn new(cx: &mut JSContext, global: &GlobalScope) -> DomRoot<UserActivation> {
35 reflect_dom_object_with_cx(Box::new(UserActivation::new_inherited()), global, cx)
36 }
37
38 pub(crate) fn handle_user_activation_notification(document: &Document) {
40 debug_assert!(
43 document.is_fully_active(),
44 "Document should be fully active at this moment"
45 );
46
47 let owner_window = document.window();
50 rooted_vec!(let mut windows <- vec![Dom::from_ref(owner_window)].into_iter());
51
52 for document in SameoriginAncestorNavigablesIterator::new(DomRoot::from_ref(document)) {
56 windows.push(Dom::from_ref(document.window()));
57 }
58
59 for document in SameOriginDescendantNavigablesIterator::new(DomRoot::from_ref(document)) {
63 windows.push(Dom::from_ref(document.window()));
64 }
65
66 let current_timestamp = CrossProcessInstant::now();
69 for window in windows.iter() {
70 window.set_last_activation_timestamp(UserActivationTimestamp::TimeStamp(
73 current_timestamp,
74 ));
75
76 }
80 }
81}
82
83impl UserActivationMethods<crate::DomTypeHolder> for UserActivation {
84 fn HasBeenActive(&self) -> bool {
86 self.global().as_window().has_sticky_activation()
88 }
89
90 fn IsActive(&self) -> bool {
92 self.global().as_window().has_transient_activation()
94 }
95}
96
97#[derive(Clone, Copy, Default, PartialEq, PartialOrd, MallocSizeOf)]
102pub(crate) enum UserActivationTimestamp {
103 NegativeInfinity,
104 TimeStamp(CrossProcessInstant),
105 #[default]
106 PositiveInfinity,
107}
108
109impl Add<i64> for UserActivationTimestamp {
110 type Output = UserActivationTimestamp;
111
112 fn add(self, rhs: i64) -> Self::Output {
113 match self {
114 UserActivationTimestamp::TimeStamp(timestamp) => {
115 UserActivationTimestamp::TimeStamp(timestamp + Duration::milliseconds(rhs))
116 },
117 _ => self,
118 }
119 }
120}