Skip to main content

script/dom/performance/
performancetiming.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use 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    /// <https://www.w3.org/TR/navigation-timing/#dom-performancetiming-redirectstart>
26    redirect_start: Cell<u64>,
27    /// <https://www.w3.org/TR/navigation-timing/#dom-performancetiming-redirectend>
28    redirect_end: Cell<u64>,
29    /// <https://www.w3.org/TR/navigation-timing/#dom-performancetiming-fetchstart>
30    fetch_start: Cell<u64>,
31    /// <https://www.w3.org/TR/navigation-timing/#dom-performancetiming-domainlookupstart>
32    domain_lookup_start: Cell<u64>,
33    /// <https://www.w3.org/TR/navigation-timing/#dom-performancetiming-domainlookupend>
34    domain_lookup_end: Cell<u64>,
35    /// <https://www.w3.org/TR/navigation-timing/#dom-performancetiming-connectstart>
36    connect_start: Cell<u64>,
37    /// <https://www.w3.org/TR/navigation-timing/#dom-performancetiming-connectend>
38    connect_end: Cell<u64>,
39    /// <https://www.w3.org/TR/navigation-timing/#dom-performancetiming-secureconnectstart>
40    secure_connection_start: Cell<u64>,
41    /// <https://www.w3.org/TR/navigation-timing/#dom-performancetiming-requeststart>
42    request_start: Cell<u64>,
43    /// <https://www.w3.org/TR/navigation-timing/#dom-performancetiming-responsestart>
44    response_start: Cell<u64>,
45    /// <https://www.w3.org/TR/navigation-timing/#dom-performancetiming-responseend>
46    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        // From <https://www.w3.org/TR/navigation-timing/#terminology>:
73        // Throughout this work, time is measured in milliseconds since midnight of January 1, 1970 (UTC).
74        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    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-navigationstart>
88    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    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-unloadeventstart
96    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    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-unloadeventend>
104    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    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-redirectstart>
112    fn RedirectStart(&self) -> u64 {
113        self.redirect_start.get()
114    }
115
116    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-redirectend>
117    fn RedirectEnd(&self) -> u64 {
118        self.redirect_end.get()
119    }
120
121    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-fetchstart>
122    fn FetchStart(&self) -> u64 {
123        self.fetch_start.get()
124    }
125
126    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-domainlookupstart>
127    fn DomainLookupStart(&self) -> u64 {
128        self.domain_lookup_start.get()
129    }
130
131    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-domainlookupend>
132    fn DomainLookupEnd(&self) -> u64 {
133        self.domain_lookup_end.get()
134    }
135
136    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-connectstart>
137    fn ConnectStart(&self) -> u64 {
138        self.connect_start.get()
139    }
140
141    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-connectend>
142    fn ConnectEnd(&self) -> u64 {
143        self.connect_end.get()
144    }
145
146    /// <https://w3c.github.io/navigation-timing#dom-performancetiming-secureconnectionstart>
147    fn SecureConnectionStart(&self) -> u64 {
148        self.secure_connection_start.get()
149    }
150
151    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-requeststart>
152    fn RequestStart(&self) -> u64 {
153        self.request_start.get()
154    }
155
156    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-responsestart>
157    fn ResponseStart(&self) -> u64 {
158        self.response_start.get()
159    }
160
161    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-responseend>
162    fn ResponseEnd(&self) -> u64 {
163        self.response_end.get()
164    }
165
166    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-domloading>
167    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    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-dominteractive>
175    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    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-domcontentloadedeventstart>
183    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    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-domcontentloadedeventend>
191    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    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-domcomplete>
199    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    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-loadeventstart>
207    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    /// <https://w3c.github.io/navigation-timing/#dom-performancetiming-loadeventend>
215    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}