diff --git a/servo/components/script/dom/document.rs b/servo/components/script/dom/document.rs index 6928d6f4977f..af1c265a8762 100644 --- a/servo/components/script/dom/document.rs +++ b/servo/components/script/dom/document.rs @@ -194,6 +194,13 @@ pub struct Document { modified_elements: DOMRefCell, ElementSnapshot>>, /// http://w3c.github.io/touch-events/#dfn-active-touch-point active_touch_points: DOMRefCell>>, + /// DOM-Related Navigation Timing properties: + /// http://w3c.github.io/navigation-timing/#widl-PerformanceTiming-domLoading + dom_loading: Cell, + dom_interactive: Cell, + dom_content_loaded_event_start: Cell, + dom_content_loaded_event_end: Cell, + dom_complete: Cell, } impl PartialEq for Document { @@ -507,6 +514,12 @@ impl Document { // https://html.spec.whatwg.org/multipage/#current-document-readiness pub fn set_ready_state(&self, state: DocumentReadyState) { + match state { + DocumentReadyState::Loading => update_with_current_time(&self.dom_loading), + DocumentReadyState::Interactive => update_with_current_time(&self.dom_interactive), + DocumentReadyState::Complete => update_with_current_time(&self.dom_complete), + }; + self.ready_state.set(state); let event = Event::new(GlobalRef::Window(&self.window), @@ -1226,6 +1239,9 @@ impl Document { return; } self.domcontentloaded_dispatched.set(true); + + update_with_current_time(&self.dom_content_loaded_event_start); + let event = Event::new(GlobalRef::Window(self.window()), DOMString::from("DOMContentLoaded"), EventBubbles::DoesNotBubble, @@ -1233,6 +1249,8 @@ impl Document { let doctarget = self.upcast::(); let _ = doctarget.DispatchEvent(event.r()); self.window().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::DOMContentLoaded); + + update_with_current_time(&self.dom_content_loaded_event_end); } pub fn notify_constellation_load(&self) { @@ -1258,6 +1276,26 @@ impl Document { .filter_map(Root::downcast::) .find(|node| node.subpage_id() == Some(subpage_id)) } + + pub fn get_dom_loading(&self) -> u64 { + self.dom_loading.get() + } + + pub fn get_dom_interactive(&self) -> u64 { + self.dom_interactive.get() + } + + pub fn get_dom_content_loaded_event_start(&self) -> u64 { + self.dom_content_loaded_event_start.get() + } + + pub fn get_dom_content_loaded_event_end(&self) -> u64 { + self.dom_content_loaded_event_end.get() + } + + pub fn get_dom_complete(&self) -> u64 { + self.dom_complete.get() + } } #[derive(HeapSizeOf)] @@ -1367,6 +1405,11 @@ impl Document { appropriate_template_contents_owner_document: Default::default(), modified_elements: DOMRefCell::new(HashMap::new()), active_touch_points: DOMRefCell::new(Vec::new()), + dom_loading: Cell::new(Default::default()), + dom_interactive: Cell::new(Default::default()), + dom_content_loaded_event_start: Cell::new(Default::default()), + dom_content_loaded_event_end: Cell::new(Default::default()), + dom_complete: Cell::new(Default::default()), } } @@ -2237,6 +2280,13 @@ fn is_scheme_host_port_tuple(url: &Url) -> bool { url.host().is_some() && url.port_or_default().is_some() } +fn update_with_current_time(marker: &Cell) { + if marker.get() == Default::default() { + let current_time_ms = time::get_time().sec * 1000; + marker.set(current_time_ms as u64); + } +} + pub struct DocumentProgressHandler { addr: Trusted } diff --git a/servo/components/script/dom/performancetiming.rs b/servo/components/script/dom/performancetiming.rs index 1799d6a7f912..c9f2458de3e4 100644 --- a/servo/components/script/dom/performancetiming.rs +++ b/servo/components/script/dom/performancetiming.rs @@ -4,9 +4,11 @@ use dom::bindings::codegen::Bindings::PerformanceTimingBinding; use dom::bindings::codegen::Bindings::PerformanceTimingBinding::PerformanceTimingMethods; +use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::global::GlobalRef; -use dom::bindings::js::Root; +use dom::bindings::js::{JS, Root}; use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::document::Document; use dom::window::Window; #[dom_struct] @@ -14,15 +16,19 @@ pub struct PerformanceTiming { reflector_: Reflector, navigationStart: u64, navigationStartPrecise: f64, + document: JS, } impl PerformanceTiming { - fn new_inherited(navStart: u64, navStartPrecise: f64) + fn new_inherited(navStart: u64, + navStartPrecise: f64, + document: &Document) -> PerformanceTiming { PerformanceTiming { reflector_: Reflector::new(), navigationStart: navStart, navigationStartPrecise: navStartPrecise, + document: JS::from_ref(document), } } @@ -31,19 +37,45 @@ impl PerformanceTiming { navigation_start: u64, navigation_start_precise: f64) -> Root { + let timing = PerformanceTiming::new_inherited(navigation_start, - navigation_start_precise); + navigation_start_precise, + window.Document().r()); reflect_dom_object(box timing, GlobalRef::Window(window), PerformanceTimingBinding::Wrap) } } impl PerformanceTimingMethods for PerformanceTiming { - // https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/ - // NavigationTiming/Overview.html#dom-performancetiming-navigationstart + // https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-navigationStart fn NavigationStart(&self) -> u64 { self.navigationStart } + + // https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-domLoading + fn DomLoading(&self) -> u64 { + self.document.get_dom_loading() + } + + // https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-domInteractive + fn DomInteractive(&self) -> u64 { + self.document.get_dom_interactive() + } + + // https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-domContentLoadedEventStart + fn DomContentLoadedEventStart(&self) -> u64 { + self.document.get_dom_content_loaded_event_start() + } + + // https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-domContentLoadedEventEnd + fn DomContentLoadedEventEnd(&self) -> u64 { + self.document.get_dom_content_loaded_event_end() + } + + // https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-domComplete + fn DomComplete(&self) -> u64 { + self.document.get_dom_complete() + } } diff --git a/servo/components/script/dom/webidls/PerformanceTiming.webidl b/servo/components/script/dom/webidls/PerformanceTiming.webidl index b066b4be2dcf..a016f2b16169 100644 --- a/servo/components/script/dom/webidls/PerformanceTiming.webidl +++ b/servo/components/script/dom/webidls/PerformanceTiming.webidl @@ -21,12 +21,12 @@ interface PerformanceTiming { readonly attribute unsigned long long secureConnectionStart; readonly attribute unsigned long long requestStart; readonly attribute unsigned long long responseStart; - readonly attribute unsigned long long responseEnd; + readonly attribute unsigned long long responseEnd; */ readonly attribute unsigned long long domLoading; readonly attribute unsigned long long domInteractive; readonly attribute unsigned long long domContentLoadedEventStart; readonly attribute unsigned long long domContentLoadedEventEnd; readonly attribute unsigned long long domComplete; - readonly attribute unsigned long long loadEventStart; + /* readonly attribute unsigned long long loadEventStart; readonly attribute unsigned long long loadEventEnd; */ }; diff --git a/servo/components/script/script_task.rs b/servo/components/script/script_task.rs index b0648f6f27cf..c3ddfdad6b3a 100644 --- a/servo/components/script/script_task.rs +++ b/servo/components/script/script_task.rs @@ -1642,6 +1642,8 @@ impl ScriptTask { let frame_element = frame_element.r().map(Castable::upcast); window.init_browsing_context(document.r(), frame_element); + document.set_ready_state(DocumentReadyState::Loading); + // Create the root frame page.set_frame(Some(Frame { document: JS::from_rooted(&document),