script/dom/performance/
performanceresourcetiming.rs1use dom_struct::dom_struct;
6use js::context::JSContext;
7use net_traits::ResourceFetchTiming;
8use script_bindings::reflector::reflect_dom_object_with_cx;
9use servo_base::cross_process_instant::CrossProcessInstant;
10use servo_url::ServoUrl;
11use time::Duration;
12
13use super::performanceentry::{EntryType, PerformanceEntry};
14use crate::dom::bindings::codegen::Bindings::PerformanceBinding::DOMHighResTimeStamp;
15use crate::dom::bindings::codegen::Bindings::PerformanceResourceTimingBinding::PerformanceResourceTimingMethods;
16use crate::dom::bindings::reflector::DomGlobal;
17use crate::dom::bindings::root::DomRoot;
18use crate::dom::bindings::str::DOMString;
19use crate::dom::globalscope::GlobalScope;
20#[derive(Debug, JSTraceable, MallocSizeOf, PartialEq)]
29pub(crate) enum InitiatorType {
30 Beacon,
31 Css,
32 LocalName(String),
33 Navigation,
34 XMLHttpRequest,
35 Fetch,
36 Other,
37}
38
39#[dom_struct]
40pub(crate) struct PerformanceResourceTiming {
41 entry: PerformanceEntry,
42 initiator_type: InitiatorType,
43 next_hop: Option<DOMString>,
44 #[no_trace]
45 worker_start: Option<CrossProcessInstant>,
46 #[no_trace]
47 redirect_start: Option<CrossProcessInstant>,
48 #[no_trace]
49 redirect_end: Option<CrossProcessInstant>,
50 #[no_trace]
51 fetch_start: Option<CrossProcessInstant>,
52 #[no_trace]
53 domain_lookup_start: Option<CrossProcessInstant>,
54 #[no_trace]
55 domain_lookup_end: Option<CrossProcessInstant>,
56 #[no_trace]
57 connect_start: Option<CrossProcessInstant>,
58 #[no_trace]
59 connect_end: Option<CrossProcessInstant>,
60 #[no_trace]
61 secure_connection_start: Option<CrossProcessInstant>,
62 #[no_trace]
63 request_start: Option<CrossProcessInstant>,
64 #[no_trace]
65 response_start: Option<CrossProcessInstant>,
66 #[no_trace]
67 response_end: Option<CrossProcessInstant>,
68 transfer_size: u64, encoded_body_size: u64, decoded_body_size: u64, }
72
73impl PerformanceResourceTiming {
77 pub(crate) fn new_inherited(
78 url: ServoUrl,
79 initiator_type: InitiatorType,
80 resource_timing: &ResourceFetchTiming,
81 ) -> PerformanceResourceTiming {
82 let (entry_type, start_time) = if initiator_type == InitiatorType::Navigation {
83 (EntryType::Navigation, None)
84 } else {
85 (EntryType::Resource, resource_timing.start_time)
86 };
87 let duration = match (resource_timing.start_time, resource_timing.response_end) {
88 (Some(start_time), Some(end_time)) => end_time - start_time,
89 _ => Duration::ZERO,
90 };
91 PerformanceResourceTiming {
92 entry: PerformanceEntry::new_inherited(
93 DOMString::from(url.into_string()),
94 entry_type,
95 start_time,
96 duration,
97 ),
98 initiator_type,
99 next_hop: None,
100 worker_start: None,
101 redirect_start: resource_timing.redirect_start,
102 redirect_end: resource_timing.redirect_end,
103 fetch_start: resource_timing.fetch_start,
104 domain_lookup_start: resource_timing.domain_lookup_start,
105 domain_lookup_end: None,
106 connect_start: resource_timing.connect_start,
107 connect_end: resource_timing.connect_end,
108 secure_connection_start: resource_timing.secure_connection_start,
109 request_start: resource_timing.request_start,
110 response_start: resource_timing.response_start,
111 response_end: resource_timing.response_end,
112 transfer_size: 0,
113 encoded_body_size: 0,
114 decoded_body_size: 0,
115 }
116 }
117
118 pub(crate) fn new(
119 cx: &mut JSContext,
120 global: &GlobalScope,
121 url: ServoUrl,
122 initiator_type: InitiatorType,
123 resource_timing: &ResourceFetchTiming,
124 ) -> DomRoot<PerformanceResourceTiming> {
125 reflect_dom_object_with_cx(
126 Box::new(PerformanceResourceTiming::new_inherited(
127 url,
128 initiator_type,
129 resource_timing,
130 )),
131 global,
132 cx,
133 )
134 }
135
136 pub(crate) fn to_dom_high_res_time_stamp(
140 &self,
141 instant: Option<CrossProcessInstant>,
142 ) -> DOMHighResTimeStamp {
143 self.global()
144 .performance()
145 .maybe_to_dom_high_res_time_stamp(instant)
146 }
147}
148
149impl PerformanceResourceTimingMethods<crate::DomTypeHolder> for PerformanceResourceTiming {
151 fn InitiatorType(&self) -> DOMString {
153 match self.initiator_type {
154 InitiatorType::Beacon => DOMString::from("beacon"),
155 InitiatorType::Css => DOMString::from("css"),
156 InitiatorType::LocalName(ref n) => DOMString::from(n.clone()),
157 InitiatorType::Navigation => DOMString::from("navigation"),
158 InitiatorType::XMLHttpRequest => DOMString::from("xmlhttprequest"),
159 InitiatorType::Fetch => DOMString::from("fetch"),
160 InitiatorType::Other => DOMString::from("other"),
161 }
162 }
163
164 fn NextHopProtocol(&self) -> DOMString {
168 match self.next_hop {
169 Some(ref protocol) => protocol.clone(),
170 None => DOMString::from(""),
171 }
172 }
173
174 fn DomainLookupStart(&self) -> DOMHighResTimeStamp {
176 self.to_dom_high_res_time_stamp(self.domain_lookup_start)
177 }
178
179 fn DomainLookupEnd(&self) -> DOMHighResTimeStamp {
181 self.to_dom_high_res_time_stamp(self.domain_lookup_end)
182 }
183
184 fn SecureConnectionStart(&self) -> DOMHighResTimeStamp {
186 self.to_dom_high_res_time_stamp(self.secure_connection_start)
187 }
188
189 fn TransferSize(&self) -> u64 {
191 self.transfer_size
192 }
193
194 fn EncodedBodySize(&self) -> u64 {
196 self.encoded_body_size
197 }
198
199 fn DecodedBodySize(&self) -> u64 {
201 self.decoded_body_size
202 }
203
204 fn RequestStart(&self) -> DOMHighResTimeStamp {
206 self.to_dom_high_res_time_stamp(self.request_start)
207 }
208
209 fn RedirectStart(&self) -> DOMHighResTimeStamp {
211 self.to_dom_high_res_time_stamp(self.redirect_start)
212 }
213
214 fn RedirectEnd(&self) -> DOMHighResTimeStamp {
216 self.to_dom_high_res_time_stamp(self.redirect_end)
217 }
218
219 fn ResponseStart(&self) -> DOMHighResTimeStamp {
221 self.to_dom_high_res_time_stamp(self.response_start)
222 }
223
224 fn FetchStart(&self) -> DOMHighResTimeStamp {
226 self.to_dom_high_res_time_stamp(self.fetch_start)
227 }
228
229 fn ConnectStart(&self) -> DOMHighResTimeStamp {
231 self.to_dom_high_res_time_stamp(self.connect_start)
232 }
233
234 fn ConnectEnd(&self) -> DOMHighResTimeStamp {
236 self.to_dom_high_res_time_stamp(self.connect_end)
237 }
238
239 fn ResponseEnd(&self) -> DOMHighResTimeStamp {
241 self.to_dom_high_res_time_stamp(self.response_end)
242 }
243}