use base::cross_process_instant::CrossProcessInstant;
use dom_struct::dom_struct;
use net_traits::ResourceFetchTiming;
use servo_url::ServoUrl;
use time_03::Duration;
use crate::dom::bindings::codegen::Bindings::PerformanceBinding::DOMHighResTimeStamp;
use crate::dom::bindings::codegen::Bindings::PerformanceResourceTimingBinding::PerformanceResourceTimingMethods;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::globalscope::GlobalScope;
use crate::dom::performanceentry::PerformanceEntry;
#[derive(Debug, JSTraceable, MallocSizeOf, PartialEq)]
pub enum InitiatorType {
LocalName(String),
Navigation,
XMLHttpRequest,
Fetch,
Other,
}
#[dom_struct]
pub struct PerformanceResourceTiming {
entry: PerformanceEntry,
initiator_type: InitiatorType,
next_hop: Option<DOMString>,
#[no_trace]
worker_start: Option<CrossProcessInstant>,
#[no_trace]
redirect_start: Option<CrossProcessInstant>,
#[no_trace]
redirect_end: Option<CrossProcessInstant>,
#[no_trace]
fetch_start: Option<CrossProcessInstant>,
#[no_trace]
domain_lookup_start: Option<CrossProcessInstant>,
#[no_trace]
domain_lookup_end: Option<CrossProcessInstant>,
#[no_trace]
connect_start: Option<CrossProcessInstant>,
#[no_trace]
connect_end: Option<CrossProcessInstant>,
#[no_trace]
secure_connection_start: Option<CrossProcessInstant>,
#[no_trace]
request_start: Option<CrossProcessInstant>,
#[no_trace]
response_start: Option<CrossProcessInstant>,
#[no_trace]
response_end: Option<CrossProcessInstant>,
transfer_size: u64, encoded_body_size: u64, decoded_body_size: u64, }
impl PerformanceResourceTiming {
pub fn new_inherited(
url: ServoUrl,
initiator_type: InitiatorType,
next_hop: Option<DOMString>,
fetch_start: Option<CrossProcessInstant>,
) -> PerformanceResourceTiming {
let entry_type = if initiator_type == InitiatorType::Navigation {
DOMString::from("navigation")
} else {
DOMString::from("resource")
};
PerformanceResourceTiming {
entry: PerformanceEntry::new_inherited(
DOMString::from(url.into_string()),
entry_type,
None,
Duration::ZERO,
),
initiator_type,
next_hop,
worker_start: None,
redirect_start: None,
redirect_end: None,
fetch_start,
domain_lookup_end: None,
domain_lookup_start: None,
connect_start: None,
connect_end: None,
secure_connection_start: None,
request_start: None,
response_start: None,
response_end: None,
transfer_size: 0,
encoded_body_size: 0,
decoded_body_size: 0,
}
}
#[allow(crown::unrooted_must_root)]
fn from_resource_timing(
url: ServoUrl,
initiator_type: InitiatorType,
next_hop: Option<DOMString>,
resource_timing: &ResourceFetchTiming,
) -> PerformanceResourceTiming {
let duration = match (resource_timing.start_time, resource_timing.response_end) {
(Some(start_time), Some(end_time)) => end_time - start_time,
_ => Duration::ZERO,
};
PerformanceResourceTiming {
entry: PerformanceEntry::new_inherited(
DOMString::from(url.into_string()),
DOMString::from("resource"),
resource_timing.start_time,
duration,
),
initiator_type,
next_hop,
worker_start: None,
redirect_start: resource_timing.redirect_start,
redirect_end: resource_timing.redirect_end,
fetch_start: resource_timing.fetch_start,
domain_lookup_start: resource_timing.domain_lookup_start,
domain_lookup_end: None,
connect_start: resource_timing.connect_start,
connect_end: resource_timing.connect_end,
secure_connection_start: resource_timing.secure_connection_start,
request_start: resource_timing.request_start,
response_start: resource_timing.response_start,
response_end: resource_timing.response_end,
transfer_size: 0,
encoded_body_size: 0,
decoded_body_size: 0,
}
}
pub fn new(
global: &GlobalScope,
url: ServoUrl,
initiator_type: InitiatorType,
next_hop: Option<DOMString>,
resource_timing: &ResourceFetchTiming,
) -> DomRoot<PerformanceResourceTiming> {
reflect_dom_object(
Box::new(PerformanceResourceTiming::from_resource_timing(
url,
initiator_type,
next_hop,
resource_timing,
)),
global,
)
}
pub(crate) fn to_dom_high_res_time_stamp(
&self,
instant: Option<CrossProcessInstant>,
) -> DOMHighResTimeStamp {
self.global()
.performance()
.maybe_to_dom_high_res_time_stamp(instant)
}
}
impl PerformanceResourceTimingMethods for PerformanceResourceTiming {
fn InitiatorType(&self) -> DOMString {
match self.initiator_type {
InitiatorType::LocalName(ref n) => DOMString::from(n.clone()),
InitiatorType::Navigation => DOMString::from("navigation"),
InitiatorType::XMLHttpRequest => DOMString::from("xmlhttprequest"),
InitiatorType::Fetch => DOMString::from("fetch"),
InitiatorType::Other => DOMString::from("other"),
}
}
fn NextHopProtocol(&self) -> DOMString {
match self.next_hop {
Some(ref protocol) => protocol.clone(),
None => DOMString::from(""),
}
}
fn DomainLookupStart(&self) -> DOMHighResTimeStamp {
self.to_dom_high_res_time_stamp(self.domain_lookup_start)
}
fn DomainLookupEnd(&self) -> DOMHighResTimeStamp {
self.to_dom_high_res_time_stamp(self.domain_lookup_end)
}
fn SecureConnectionStart(&self) -> DOMHighResTimeStamp {
self.to_dom_high_res_time_stamp(self.secure_connection_start)
}
fn TransferSize(&self) -> u64 {
self.transfer_size
}
fn EncodedBodySize(&self) -> u64 {
self.encoded_body_size
}
fn DecodedBodySize(&self) -> u64 {
self.decoded_body_size
}
fn RequestStart(&self) -> DOMHighResTimeStamp {
self.to_dom_high_res_time_stamp(self.request_start)
}
fn RedirectStart(&self) -> DOMHighResTimeStamp {
self.to_dom_high_res_time_stamp(self.redirect_start)
}
fn RedirectEnd(&self) -> DOMHighResTimeStamp {
self.to_dom_high_res_time_stamp(self.redirect_end)
}
fn ResponseStart(&self) -> DOMHighResTimeStamp {
self.to_dom_high_res_time_stamp(self.response_start)
}
fn FetchStart(&self) -> DOMHighResTimeStamp {
self.to_dom_high_res_time_stamp(self.fetch_start)
}
fn ConnectStart(&self) -> DOMHighResTimeStamp {
self.to_dom_high_res_time_stamp(self.connect_start)
}
fn ConnectEnd(&self) -> DOMHighResTimeStamp {
self.to_dom_high_res_time_stamp(self.connect_end)
}
fn ResponseEnd(&self) -> DOMHighResTimeStamp {
self.to_dom_high_res_time_stamp(self.response_end)
}
}