script/dom/performance/
performancetiming.rs1use std::cell::Cell;
6use std::rc::Rc;
7
8use dom_struct::dom_struct;
9use js::context::JSContext;
10use script_bindings::codegen::GenericBindings::WindowBinding::WindowMethods;
11use script_bindings::inheritance::Castable;
12use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
13use script_bindings::root::DomRoot;
14use servo_base::cross_process_instant::CrossProcessInstant;
15
16use crate::dom::bindings::codegen::Bindings::PerformanceTimingBinding::PerformanceTimingMethods;
17use crate::dom::bindings::reflector::DomGlobal;
18use crate::dom::document::document::NavigationTiming;
19use crate::dom::globalscope::GlobalScope;
20use crate::dom::window::Window;
21
22#[dom_struct]
23pub(crate) struct PerformanceTiming {
24 reflector_: Reflector,
25 redirect_start: Cell<u64>,
27 redirect_end: Cell<u64>,
29 fetch_start: Cell<u64>,
31 domain_lookup_start: Cell<u64>,
33 domain_lookup_end: Cell<u64>,
35 connect_start: Cell<u64>,
37 connect_end: Cell<u64>,
39 secure_connection_start: Cell<u64>,
41 request_start: Cell<u64>,
43 response_start: Cell<u64>,
45 response_end: Cell<u64>,
47}
48
49impl PerformanceTiming {
50 pub(crate) fn new_inherited() -> PerformanceTiming {
51 PerformanceTiming {
52 reflector_: Reflector::new(),
53 redirect_start: Default::default(),
54 redirect_end: Default::default(),
55 fetch_start: Default::default(),
56 domain_lookup_start: Default::default(),
57 domain_lookup_end: Default::default(),
58 connect_start: Default::default(),
59 connect_end: Default::default(),
60 secure_connection_start: Default::default(),
61 request_start: Default::default(),
62 response_start: Default::default(),
63 response_end: Default::default(),
64 }
65 }
66
67 pub(crate) fn new(cx: &mut JSContext, global: &GlobalScope) -> DomRoot<PerformanceTiming> {
68 reflect_dom_object_with_cx(Box::new(PerformanceTiming::new_inherited()), global, cx)
69 }
70
71 fn instant_to_millis(instant: Option<CrossProcessInstant>) -> u64 {
72 let instant = instant.unwrap_or(CrossProcessInstant::epoch());
75 let epoch = CrossProcessInstant::epoch();
76 (instant - epoch).whole_milliseconds() as u64
77 }
78
79 fn navigation_timing(&self) -> Option<Rc<NavigationTiming>> {
80 self.global()
81 .downcast::<Window>()
82 .map(|window| window.Document().navigation_timing())
83 }
84}
85
86impl PerformanceTimingMethods<crate::DomTypeHolder> for PerformanceTiming {
87 fn NavigationStart(&self) -> u64 {
89 Self::instant_to_millis(
90 self.navigation_timing()
91 .and_then(|timing| timing.navigation_start.get()),
92 )
93 }
94
95 fn UnloadEventStart(&self) -> u64 {
97 Self::instant_to_millis(
98 self.navigation_timing()
99 .and_then(|timing| timing.unload_event_start.get()),
100 )
101 }
102
103 fn UnloadEventEnd(&self) -> u64 {
105 Self::instant_to_millis(
106 self.navigation_timing()
107 .and_then(|timing| timing.unload_event_end.get()),
108 )
109 }
110
111 fn RedirectStart(&self) -> u64 {
113 self.redirect_start.get()
114 }
115
116 fn RedirectEnd(&self) -> u64 {
118 self.redirect_end.get()
119 }
120
121 fn FetchStart(&self) -> u64 {
123 self.fetch_start.get()
124 }
125
126 fn DomainLookupStart(&self) -> u64 {
128 self.domain_lookup_start.get()
129 }
130
131 fn DomainLookupEnd(&self) -> u64 {
133 self.domain_lookup_end.get()
134 }
135
136 fn ConnectStart(&self) -> u64 {
138 self.connect_start.get()
139 }
140
141 fn ConnectEnd(&self) -> u64 {
143 self.connect_end.get()
144 }
145
146 fn SecureConnectionStart(&self) -> u64 {
148 self.secure_connection_start.get()
149 }
150
151 fn RequestStart(&self) -> u64 {
153 self.request_start.get()
154 }
155
156 fn ResponseStart(&self) -> u64 {
158 self.response_start.get()
159 }
160
161 fn ResponseEnd(&self) -> u64 {
163 self.response_end.get()
164 }
165
166 fn DomLoading(&self) -> u64 {
168 Self::instant_to_millis(
169 self.navigation_timing()
170 .and_then(|timing| timing.dom_loading.get()),
171 )
172 }
173
174 fn DomInteractive(&self) -> u64 {
176 Self::instant_to_millis(
177 self.navigation_timing()
178 .and_then(|timing| timing.dom_interactive.get()),
179 )
180 }
181
182 fn DomContentLoadedEventStart(&self) -> u64 {
184 Self::instant_to_millis(
185 self.navigation_timing()
186 .and_then(|timing| timing.dom_content_loaded_event_start.get()),
187 )
188 }
189
190 fn DomContentLoadedEventEnd(&self) -> u64 {
192 Self::instant_to_millis(
193 self.navigation_timing()
194 .and_then(|timing| timing.dom_content_loaded_event_end.get()),
195 )
196 }
197
198 fn DomComplete(&self) -> u64 {
200 Self::instant_to_millis(
201 self.navigation_timing()
202 .and_then(|timing| timing.dom_complete.get()),
203 )
204 }
205
206 fn LoadEventStart(&self) -> u64 {
208 Self::instant_to_millis(
209 self.navigation_timing()
210 .and_then(|timing| timing.load_event_start.get()),
211 )
212 }
213
214 fn LoadEventEnd(&self) -> u64 {
216 Self::instant_to_millis(
217 self.navigation_timing()
218 .and_then(|timing| timing.load_event_end.get()),
219 )
220 }
221}