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