diff options
author | Tommy Lincoln <pajamapants3000@gmail.com> | 2019-10-15 03:06:43 -0700 |
---|---|---|
committer | Tommy Lincoln <pajamapants3000@gmail.com> | 2019-10-20 07:28:11 -0700 |
commit | fcad88cddd873309fafa7582f78e07bcae2d0565 (patch) | |
tree | f7c1e0dd57a403086e03c1c0c94e908b46ef6ac3 /components | |
parent | 1f6402465579e787e63b34b24ac46593c27c2f3d (diff) | |
download | servo-fcad88cddd873309fafa7582f78e07bcae2d0565.tar.gz servo-fcad88cddd873309fafa7582f78e07bcae2d0565.zip |
Add start_time to resource timing.
Diffstat (limited to 'components')
-rw-r--r-- | components/net/fetch/methods.rs | 11 | ||||
-rw-r--r-- | components/net/http_loader.rs | 21 | ||||
-rw-r--r-- | components/net_traits/lib.rs | 30 | ||||
-rw-r--r-- | components/net_traits/tests/lib.rs | 215 | ||||
-rw-r--r-- | components/script/dom/performanceresourcetiming.rs | 3 |
5 files changed, 272 insertions, 8 deletions
diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs index b60265ce2b8..d2250aa897a 100644 --- a/components/net/fetch/methods.rs +++ b/components/net/fetch/methods.rs @@ -21,8 +21,8 @@ use net_traits::filemanager_thread::RelativePos; use net_traits::request::{CredentialsMode, Destination, Referrer, Request, RequestMode}; use net_traits::request::{Origin, ResponseTainting, Window}; use net_traits::response::{Response, ResponseBody, ResponseType}; -use net_traits::ResourceAttribute; use net_traits::{FetchTaskTarget, NetworkError, ReferrerPolicy, ResourceFetchTiming}; +use net_traits::{ResourceAttribute, ResourceTimeValue}; use servo_arc::Arc as ServoArc; use servo_url::ServoUrl; use std::borrow::Cow; @@ -89,12 +89,19 @@ pub type DoneChannel = Option<(Sender<Data>, Receiver<Data>)>; /// [Fetch](https://fetch.spec.whatwg.org#concept-fetch) pub fn fetch(request: &mut Request, target: Target, context: &FetchContext) { - // Step 7 of https://w3c.github.io/resource-timing/#processing-model + // Steps 7,4 of https://w3c.github.io/resource-timing/#processing-model + // rev order okay since spec says they're equal - https://w3c.github.io/resource-timing/#dfn-starttime context .timing .lock() .unwrap() .set_attribute(ResourceAttribute::FetchStart); + context + .timing + .lock() + .unwrap() + .set_attribute(ResourceAttribute::StartTime(ResourceTimeValue::FetchStart)); + fetch_with_cors_cache(request, &mut CorsCache::new(), target, context); } diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index baf55b24faa..3bd8acce355 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -43,7 +43,9 @@ use net_traits::request::{RedirectMode, Referrer, Request, RequestBuilder, Reque use net_traits::request::{ResponseTainting, ServiceWorkersMode}; use net_traits::response::{HttpsState, Response, ResponseBody, ResponseType}; use net_traits::{CookieSource, FetchMetadata, NetworkError, ReferrerPolicy}; -use net_traits::{RedirectEndValue, RedirectStartValue, ResourceAttribute, ResourceFetchTiming}; +use net_traits::{ + RedirectEndValue, RedirectStartValue, ResourceAttribute, ResourceFetchTiming, ResourceTimeValue, +}; use openssl::ssl::SslConnectorBuilder; use servo_arc::Arc; use servo_url::{ImmutableOrigin, ServoUrl}; @@ -572,8 +574,6 @@ pub fn http_fetch( // Generally, we use a persistent connection, so we will also set other PerformanceResourceTiming // attributes to this as well (domain_lookup_start, domain_lookup_end, connect_start, connect_end, // secure_connection_start) - // TODO(#21254) also set startTime equal to either fetch_start or redirect_start - // (https://w3c.github.io/resource-timing/#dfn-starttime) context .timing .lock() @@ -737,6 +737,21 @@ pub fn http_redirect_fetch( .unwrap() .set_attribute(ResourceAttribute::FetchStart); + // start_time should equal redirect_start if nonzero; else fetch_start + context + .timing + .lock() + .unwrap() + .set_attribute(ResourceAttribute::StartTime(ResourceTimeValue::FetchStart)); + + context + .timing + .lock() + .unwrap() + .set_attribute(ResourceAttribute::StartTime( + ResourceTimeValue::RedirectStart, + )); // updates start_time only if redirect_start is nonzero (implying TAO) + // Step 5 if request.redirect_count >= 20 { return Response::network_error(NetworkError::Internal("Too many redirects".into())); diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index ae6d8797adb..cdba4f2066d 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -474,6 +474,7 @@ pub struct ResourceFetchTiming { pub redirect_end: u64, pub connect_start: u64, pub connect_end: u64, + pub start_time: u64, } pub enum RedirectStartValue { @@ -487,6 +488,15 @@ pub enum RedirectEndValue { ResponseEnd, } +// TODO: refactor existing code to use this enum for setting time attributes +// suggest using this with all time attributes in the future +pub enum ResourceTimeValue { + Zero, + Now, + FetchStart, + RedirectStart, +} + pub enum ResourceAttribute { RedirectCount(u16), DomainLookupStart, @@ -499,6 +509,7 @@ pub enum ResourceAttribute { ConnectEnd(u64), SecureConnectionStart, ResponseEnd, + StartTime(ResourceTimeValue), } #[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] @@ -525,6 +536,7 @@ impl ResourceFetchTiming { connect_start: 0, connect_end: 0, response_end: 0, + start_time: 0, } } @@ -532,7 +544,9 @@ impl ResourceFetchTiming { // time origin (as described in Performance::now) pub fn set_attribute(&mut self, attribute: ResourceAttribute) { let should_attribute_always_be_updated = match attribute { - ResourceAttribute::FetchStart | ResourceAttribute::ResponseEnd => true, + ResourceAttribute::FetchStart | + ResourceAttribute::ResponseEnd | + ResourceAttribute::StartTime(_) => true, _ => false, }; if !self.timing_check_passed && !should_attribute_always_be_updated { @@ -562,6 +576,20 @@ impl ResourceFetchTiming { self.secure_connection_start = precise_time_ns() }, ResourceAttribute::ResponseEnd => self.response_end = precise_time_ns(), + ResourceAttribute::StartTime(val) => match val { + ResourceTimeValue::RedirectStart + if self.redirect_start == 0 || !self.timing_check_passed => {}, + _ => self.start_time = self.get_time_value(val), + }, + } + } + + fn get_time_value(&self, time: ResourceTimeValue) -> u64 { + match time { + ResourceTimeValue::Zero => 0, + ResourceTimeValue::Now => precise_time_ns(), + ResourceTimeValue::FetchStart => self.fetch_start, + ResourceTimeValue::RedirectStart => self.redirect_start, } } diff --git a/components/net_traits/tests/lib.rs b/components/net_traits/tests/lib.rs new file mode 100644 index 00000000000..d54b77edb6a --- /dev/null +++ b/components/net_traits/tests/lib.rs @@ -0,0 +1,215 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use net_traits::{ResourceAttribute, ResourceFetchTiming, ResourceTimeValue, ResourceTimingType}; + +#[test] +fn test_set_start_time_to_fetch_start_if_nonzero_tao() { + let mut resource_timing: ResourceFetchTiming = + ResourceFetchTiming::new(ResourceTimingType::Resource); + resource_timing.fetch_start = 1; + assert_eq!(resource_timing.start_time, 0, "`start_time` should be zero"); + assert!( + resource_timing.fetch_start > 0, + "`fetch_start` should have a positive value" + ); + + // verify that setting `start_time` to `fetch_start` succeeds + resource_timing.set_attribute(ResourceAttribute::StartTime(ResourceTimeValue::FetchStart)); + assert_eq!( + resource_timing.start_time, resource_timing.fetch_start, + "`start_time` should equal `fetch_start`" + ); +} + +#[test] +fn test_set_start_time_to_fetch_start_if_zero_tao() { + let mut resource_timing: ResourceFetchTiming = + ResourceFetchTiming::new(ResourceTimingType::Resource); + resource_timing.start_time = 1; + assert!( + resource_timing.start_time > 0, + "`start_time` should have a positive value" + ); + assert_eq!( + resource_timing.fetch_start, 0, + "`fetch_start` should be zero" + ); + + // verify that setting `start_time` to `fetch_start` succeeds even when `fetch_start` == zero + resource_timing.set_attribute(ResourceAttribute::StartTime(ResourceTimeValue::FetchStart)); + assert_eq!( + resource_timing.start_time, resource_timing.fetch_start, + "`start_time` should equal `fetch_start`" + ); +} + +#[test] +fn test_set_start_time_to_fetch_start_if_nonzero_no_tao() { + let mut resource_timing: ResourceFetchTiming = + ResourceFetchTiming::new(ResourceTimingType::Resource); + resource_timing.mark_timing_check_failed(); + resource_timing.fetch_start = 1; + assert_eq!(resource_timing.start_time, 0, "`start_time` should be zero"); + assert!( + resource_timing.fetch_start > 0, + "`fetch_start` should have a positive value" + ); + + // verify that setting `start_time` to `fetch_start` succeeds even when TAO check failed + resource_timing.set_attribute(ResourceAttribute::StartTime(ResourceTimeValue::FetchStart)); + assert_eq!( + resource_timing.start_time, resource_timing.fetch_start, + "`start_time` should equal `fetch_start`" + ); +} + +#[test] +fn test_set_start_time_to_fetch_start_if_zero_no_tao() { + let mut resource_timing: ResourceFetchTiming = + ResourceFetchTiming::new(ResourceTimingType::Resource); + resource_timing.mark_timing_check_failed(); + resource_timing.start_time = 1; + assert!( + resource_timing.start_time > 0, + "`start_time` should have a positive value" + ); + assert_eq!( + resource_timing.fetch_start, 0, + "`fetch_start` should be zero" + ); + + // verify that setting `start_time` to `fetch_start` succeeds even when `fetch_start`==0 and no TAO + resource_timing.set_attribute(ResourceAttribute::StartTime(ResourceTimeValue::FetchStart)); + assert_eq!( + resource_timing.start_time, resource_timing.fetch_start, + "`start_time` should equal `fetch_start`" + ); +} + +#[test] +fn test_set_start_time_to_redirect_start_if_nonzero_tao() { + let mut resource_timing: ResourceFetchTiming = + ResourceFetchTiming::new(ResourceTimingType::Resource); + resource_timing.redirect_start = 1; + assert_eq!(resource_timing.start_time, 0, "`start_time` should be zero"); + assert!( + resource_timing.redirect_start > 0, + "`redirect_start` should have a positive value" + ); + + // verify that setting `start_time` to `redirect_start` succeeds for nonzero `redirect_start`, TAO pass + resource_timing.set_attribute(ResourceAttribute::StartTime( + ResourceTimeValue::RedirectStart, + )); + assert_eq!( + resource_timing.start_time, resource_timing.redirect_start, + "`start_time` should equal `redirect_start`" + ); +} + +#[test] +fn test_not_set_start_time_to_redirect_start_if_zero_tao() { + let mut resource_timing: ResourceFetchTiming = + ResourceFetchTiming::new(ResourceTimingType::Resource); + resource_timing.start_time = 1; + assert!( + resource_timing.start_time > 0, + "`start_time` should have a positive value" + ); + assert_eq!( + resource_timing.redirect_start, 0, + "`redirect_start` should be zero" + ); + + // verify that setting `start_time` to `redirect_start` fails if `redirect_start` == 0 + resource_timing.set_attribute(ResourceAttribute::StartTime( + ResourceTimeValue::RedirectStart, + )); + assert_ne!( + resource_timing.start_time, resource_timing.redirect_start, + "`start_time` should *not* equal `redirect_start`" + ); +} + +#[test] +fn test_not_set_start_time_to_redirect_start_if_nonzero_no_tao() { + let mut resource_timing: ResourceFetchTiming = + ResourceFetchTiming::new(ResourceTimingType::Resource); + resource_timing.mark_timing_check_failed(); + // Note: properly-behaved redirect_start should never be nonzero once TAO check has failed + resource_timing.redirect_start = 1; + assert_eq!(resource_timing.start_time, 0, "`start_time` should be zero"); + assert!( + resource_timing.redirect_start > 0, + "`redirect_start` should have a positive value" + ); + + // verify that setting `start_time` to `redirect_start` fails if TAO check fails + resource_timing.set_attribute(ResourceAttribute::StartTime( + ResourceTimeValue::RedirectStart, + )); + assert_ne!( + resource_timing.start_time, resource_timing.redirect_start, + "`start_time` should *not* equal `redirect_start`" + ); +} + +#[test] +fn test_not_set_start_time_to_redirect_start_if_zero_no_tao() { + let mut resource_timing: ResourceFetchTiming = + ResourceFetchTiming::new(ResourceTimingType::Resource); + resource_timing.mark_timing_check_failed(); + resource_timing.start_time = 1; + assert!( + resource_timing.start_time > 0, + "`start_time` should have a positive value" + ); + assert_eq!( + resource_timing.redirect_start, 0, + "`redirect_start` should be zero" + ); + + // verify that setting `start_time` to `redirect_start` fails if `redirect_start`==0 and no TAO + resource_timing.set_attribute(ResourceAttribute::StartTime( + ResourceTimeValue::RedirectStart, + )); + assert_ne!( + resource_timing.start_time, resource_timing.redirect_start, + "`start_time` should *not* equal `redirect_start`" + ); +} + +#[test] +fn test_set_start_time() { + let mut resource_timing: ResourceFetchTiming = + ResourceFetchTiming::new(ResourceTimingType::Resource); + assert_eq!( + resource_timing.start_time, 0, + "initial `start_time` should be zero" + ); + + // verify setting `start_time` to current time succeeds + resource_timing.set_attribute(ResourceAttribute::StartTime(ResourceTimeValue::Now)); + assert!(resource_timing.start_time > 0, "failed to set `start_time`"); +} +#[test] +fn test_reset_start_time() { + let mut resource_timing: ResourceFetchTiming = + ResourceFetchTiming::new(ResourceTimingType::Resource); + assert_eq!(resource_timing.start_time, 0, "initial `start_time` = 0"); + + resource_timing.start_time = 1; + assert!( + resource_timing.start_time > 0, + "`start_time` should have a positive value" + ); + + // verify resetting `start_time` (to zero) succeeds + resource_timing.set_attribute(ResourceAttribute::StartTime(ResourceTimeValue::Zero)); + assert_eq!( + resource_timing.start_time, 0, + "failed to reset `start_time`" + ); +} diff --git a/components/script/dom/performanceresourcetiming.rs b/components/script/dom/performanceresourcetiming.rs index d3fc054d27b..735d13a31f4 100644 --- a/components/script/dom/performanceresourcetiming.rs +++ b/components/script/dom/performanceresourcetiming.rs @@ -55,7 +55,6 @@ pub struct PerformanceResourceTiming { decoded_body_size: u64, //size in octets } -// TODO(#21254): startTime // TODO(#21255): duration // TODO(#21269): next_hop // TODO(#21264): worker_start @@ -115,7 +114,7 @@ impl PerformanceResourceTiming { entry: PerformanceEntry::new_inherited( DOMString::from(url.into_string()), DOMString::from("resource"), - 0., + resource_timing.start_time as f64, 0., ), initiator_type: initiator_type, |