diff options
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | components/devtools/actors/network_event.rs | 16 | ||||
-rw-r--r-- | components/hyper_serde/Cargo.toml | 3 | ||||
-rw-r--r-- | components/hyper_serde/lib.rs | 24 | ||||
-rw-r--r-- | components/hyper_serde/tests/supported.rs | 5 | ||||
-rw-r--r-- | components/hyper_serde/tests/tokens.rs | 17 | ||||
-rw-r--r-- | components/net/cookie.rs | 29 | ||||
-rw-r--r-- | components/net/cookie_storage.rs | 28 | ||||
-rw-r--r-- | components/net/fetch/cors_cache.rs | 20 | ||||
-rw-r--r-- | components/net/hsts.rs | 26 | ||||
-rw-r--r-- | components/net/http_cache.rs | 75 | ||||
-rw-r--r-- | components/net/http_loader.rs | 6 | ||||
-rw-r--r-- | components/net/tests/hsts.rs | 34 |
13 files changed, 161 insertions, 123 deletions
diff --git a/Cargo.lock b/Cargo.lock index 71f8f364a15..c2776351f69 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2802,6 +2802,7 @@ dependencies = [ name = "hyper_serde" version = "0.13.2" dependencies = [ + "chrono", "cookie 0.12.0", "headers", "http", diff --git a/components/devtools/actors/network_event.rs b/components/devtools/actors/network_event.rs index af360d46ca2..28acde19cfd 100644 --- a/components/devtools/actors/network_event.rs +++ b/components/devtools/actors/network_event.rs @@ -9,7 +9,7 @@ use std::net::TcpStream; use std::time::{SystemTime, UNIX_EPOCH}; -use chrono::{Local, LocalResult, TimeZone}; +use chrono::{DateTime, Local}; use devtools_traits::{HttpRequest as DevtoolsHttpRequest, HttpResponse as DevtoolsHttpResponse}; use headers::{ContentType, Cookie, HeaderMapExt}; use http::{header, HeaderMap, Method, StatusCode}; @@ -371,23 +371,13 @@ impl NetworkEventActor { pub fn event_actor(&self) -> EventActor { // TODO: Send the correct values for startedDateTime, isXHR, private - let started_datetime_rfc3339 = match Local.timestamp_millis_opt( - self.request - .startedDateTime - .duration_since(UNIX_EPOCH) - .unwrap_or_default() - .as_millis() as i64, - ) { - LocalResult::None => "".to_owned(), - LocalResult::Single(dateTime) => format!("{}", dateTime.to_rfc3339()), - LocalResult::Ambiguous(dateTime, _) => format!("{}", dateTime.to_rfc3339()), - }; + let date_time: DateTime<Local> = self.request.startedDateTime.clone().into(); EventActor { actor: self.name(), url: self.request.url.clone(), method: format!("{}", self.request.method), - startedDateTime: started_datetime_rfc3339, + startedDateTime: date_time.to_rfc3339(), timeStamp: self.request.timeStamp, isXHR: self.is_xhr, private: false, diff --git a/components/hyper_serde/Cargo.toml b/components/hyper_serde/Cargo.toml index 566027fc279..736eca035f5 100644 --- a/components/hyper_serde/Cargo.toml +++ b/components/hyper_serde/Cargo.toml @@ -16,6 +16,7 @@ doctest = false test = false [dependencies] +chrono = "0.4" cookie = { workspace = true } headers = { workspace = true } http = { workspace = true } @@ -23,7 +24,7 @@ hyper = { workspace = true } mime = { workspace = true } serde = { workspace = true } serde_bytes = { workspace = true } -time = { workspace = true } [dev-dependencies] serde_test = "1.0" +time = { workspace = true } diff --git a/components/hyper_serde/lib.rs b/components/hyper_serde/lib.rs index 4df1983ea7a..735f08cf44b 100644 --- a/components/hyper_serde/lib.rs +++ b/components/hyper_serde/lib.rs @@ -20,7 +20,7 @@ //! * `hyper::Method` //! * `hyper::Uri` //! * `mime::Mime` -//! * `time::Tm` +//! * `std::time::SystemTime` //! //! # How do I use a data type with a `HeaderMap` member with Serde? //! @@ -66,8 +66,10 @@ use std::ops::{Deref, DerefMut}; use std::str::FromStr; +use std::time::SystemTime; use std::{cmp, fmt, str}; +use chrono::{DateTime, SecondsFormat, Utc}; use cookie::Cookie; use headers::ContentType; use http::HeaderMap; @@ -78,7 +80,6 @@ use serde::de::{self, Error, MapAccess, SeqAccess, Visitor}; use serde::ser::{SerializeMap, SerializeSeq}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_bytes::{ByteBuf, Bytes}; -use time::{strptime, Tm}; /// Deserialises a `T` value with a given deserializer. /// @@ -604,15 +605,15 @@ impl<'de> Visitor<'de> for StatusVisitor { } } -impl<'de> Deserialize<'de> for De<Tm> { +impl<'de> Deserialize<'de> for De<SystemTime> { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>, { - struct TmVisitor; + struct SystemTimeVisitor; - impl<'de> Visitor<'de> for TmVisitor { - type Value = De<Tm>; + impl<'de> Visitor<'de> for SystemTimeVisitor { + type Value = De<SystemTime>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "a date and time according to RFC 3339") @@ -622,22 +623,23 @@ impl<'de> Deserialize<'de> for De<Tm> { where E: de::Error, { - strptime(v, "%Y-%m-%dT%H:%M:%SZ") - .map(De::new) + DateTime::parse_from_rfc3339(v) + .map(|t| De::new(SystemTime::from(t))) .map_err(|e| E::custom(e.to_string())) } } - deserializer.deserialize_string(TmVisitor) + deserializer.deserialize_string(SystemTimeVisitor) } } -impl<'a> Serialize for Ser<'a, Tm> { +impl<'a> Serialize for Ser<'a, SystemTime> { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, { - serializer.serialize_str(&self.v.rfc3339().to_string()) + let date_time: DateTime<Utc> = self.v.clone().into(); + serializer.serialize_str(&date_time.to_rfc3339_opts(SecondsFormat::Secs, true)) } } diff --git a/components/hyper_serde/tests/supported.rs b/components/hyper_serde/tests/supported.rs index 54480903c7e..4eddd69adef 100644 --- a/components/hyper_serde/tests/supported.rs +++ b/components/hyper_serde/tests/supported.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::time::SystemTime; + use cookie::Cookie; use headers::ContentType; use http::header::HeaderMap; @@ -15,7 +17,6 @@ use hyper::{Method, StatusCode, Uri}; use hyper_serde::{De, Ser, Serde}; use mime::Mime; use serde::{Deserialize, Serialize}; -use time::Tm; fn is_supported<T>() where @@ -33,6 +34,6 @@ fn supported() { is_supported::<Method>(); is_supported::<Mime>(); is_supported::<StatusCode>(); - is_supported::<Tm>(); + is_supported::<SystemTime>(); is_supported::<Uri>(); } diff --git a/components/hyper_serde/tests/tokens.rs b/components/hyper_serde/tests/tokens.rs index d7ad09f4e9c..2ba79ce3bb6 100644 --- a/components/hyper_serde/tests/tokens.rs +++ b/components/hyper_serde/tests/tokens.rs @@ -15,7 +15,6 @@ use http::StatusCode; use hyper::{Method, Uri}; use hyper_serde::{De, Ser}; use serde_test::{assert_de_tokens, assert_ser_tokens, Token}; -use time::Duration; #[test] fn test_content_type() { @@ -32,7 +31,7 @@ fn test_cookie() { // string with a bunch of indices in it which apparently is different from the exact same // cookie but parsed as a bunch of strings. let cookie: Cookie = Cookie::build("Hello", "World!") - .max_age(Duration::seconds(42)) + .max_age(time::Duration::seconds(42)) .domain("servo.org") .path("/") .secure(true) @@ -112,14 +111,18 @@ fn test_raw_status() { } #[test] -fn test_tm() { - use time::strptime; +fn test_system_time_serialization() { + use std::time::SystemTime; - let time = strptime("2017-02-22T12:03:31Z", "%Y-%m-%dT%H:%M:%SZ").unwrap(); - let tokens = &[Token::Str("2017-02-22T12:03:31Z")]; + use chrono::{NaiveDateTime, TimeZone, Utc}; + + let time = SystemTime::from(Utc.from_utc_datetime( + &NaiveDateTime::parse_from_str("2023-01-15T12:53:31Z", "%Y-%m-%dT%H:%M:%SZ").unwrap(), + )); + let tokens = &[Token::Str("2023-01-15T12:53:31Z")]; - assert_ser_tokens(&Ser::new(&time), tokens); assert_de_tokens(&De::new(time), tokens); + assert_ser_tokens(&Ser::new(&time), tokens); } #[test] diff --git a/components/net/cookie.rs b/components/net/cookie.rs index d65c98daf18..f00bd897e50 100644 --- a/components/net/cookie.rs +++ b/components/net/cookie.rs @@ -7,13 +7,13 @@ use std::borrow::ToOwned; use std::net::{Ipv4Addr, Ipv6Addr}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; use hyper_serde::Serde; use net_traits::pub_domains::is_pub_domain; use net_traits::CookieSource; use serde::{Deserialize, Serialize}; use servo_url::ServoUrl; -use time::{at, now, Duration, Tm}; /// A stored cookie that wraps the definition in cookie-rs. This is used to implement /// various behaviours defined in the spec that rely on an associated request URL, @@ -31,13 +31,13 @@ pub struct Cookie { deserialize_with = "hyper_serde::deserialize", serialize_with = "hyper_serde::serialize" )] - pub creation_time: Tm, + pub creation_time: SystemTime, #[serde( deserialize_with = "hyper_serde::deserialize", serialize_with = "hyper_serde::serialize" )] - pub last_access: Tm, - pub expiry_time: Option<Serde<Tm>>, + pub last_access: SystemTime, + pub expiry_time: Option<Serde<SystemTime>>, } impl Cookie { @@ -62,11 +62,16 @@ impl Cookie { let (persistent, expiry_time) = match (cookie.max_age(), cookie.expires()) { (Some(max_age), _) => ( true, - Some(at( - now().to_timespec() + Duration::seconds(max_age.num_seconds()) - )), + Some(SystemTime::now() + Duration::from_secs(max_age.num_seconds() as u64)), + ), + (_, Some(expires)) => ( + true, + Some( + UNIX_EPOCH + + Duration::from_secs(expires.to_timespec().sec as u64) + + Duration::from_nanos(expires.to_timespec().nsec as u64), + ), ), - (_, Some(expires)) => (true, Some(expires)), _ => (false, None), }; @@ -135,18 +140,18 @@ impl Cookie { cookie, host_only, persistent, - creation_time: now(), - last_access: now(), + creation_time: SystemTime::now(), + last_access: SystemTime::now(), expiry_time: expiry_time.map(Serde), }) } pub fn touch(&mut self) { - self.last_access = now(); + self.last_access = SystemTime::now(); } pub fn set_expiry_time_negative(&mut self) { - self.expiry_time = Some(Serde(now() - Duration::seconds(1))); + self.expiry_time = Some(Serde(SystemTime::now() - Duration::from_secs(1))); } // http://tools.ietf.org/html/rfc6265#section-5.1.4 diff --git a/components/net/cookie_storage.rs b/components/net/cookie_storage.rs index e1ee56e0967..282a83e5fbf 100644 --- a/components/net/cookie_storage.rs +++ b/components/net/cookie_storage.rs @@ -8,13 +8,13 @@ use std::cmp::Ordering; use std::collections::hash_map::Entry; use std::collections::HashMap; +use std::time::{SystemTime, UNIX_EPOCH}; use log::{debug, info}; use net_traits::pub_domains::reg_suffix; use net_traits::CookieSource; use serde::{Deserialize, Serialize}; use servo_url::ServoUrl; -use time::{self, Tm}; use crate::cookie::Cookie; @@ -139,8 +139,17 @@ impl CookieStorage { let b_path_len = b.cookie.path().as_ref().map_or(0, |p| p.len()); match a_path_len.cmp(&b_path_len) { Ordering::Equal => { - let a_creation_time = a.creation_time.to_timespec(); - let b_creation_time = b.creation_time.to_timespec(); + let a_creation_time = a + .creation_time + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_nanos(); + let b_creation_time = b + .creation_time + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_nanos(); + a_creation_time.cmp(&b_creation_time) }, // Ensure that longer paths are sorted earlier than shorter paths @@ -229,14 +238,14 @@ fn reg_host<'a>(url: &'a str) -> String { fn is_cookie_expired(cookie: &Cookie) -> bool { match cookie.expiry_time { - Some(ref t) => t.to_timespec() <= time::get_time(), + Some(ref t) => t.0 <= SystemTime::now(), None => false, } } fn evict_one_cookie(is_secure_cookie: bool, cookies: &mut Vec<Cookie>) -> bool { // Remove non-secure cookie with oldest access time - let oldest_accessed: Option<(usize, Tm)> = get_oldest_accessed(false, cookies); + let oldest_accessed = get_oldest_accessed(false, cookies); if let Some((index, _)) = oldest_accessed { cookies.remove(index); @@ -245,7 +254,7 @@ fn evict_one_cookie(is_secure_cookie: bool, cookies: &mut Vec<Cookie>) -> bool { if !is_secure_cookie { return false; } - let oldest_accessed: Option<(usize, Tm)> = get_oldest_accessed(true, cookies); + let oldest_accessed: Option<(usize, SystemTime)> = get_oldest_accessed(true, cookies); if let Some((index, _)) = oldest_accessed { cookies.remove(index); } @@ -253,8 +262,11 @@ fn evict_one_cookie(is_secure_cookie: bool, cookies: &mut Vec<Cookie>) -> bool { return true; } -fn get_oldest_accessed(is_secure_cookie: bool, cookies: &mut Vec<Cookie>) -> Option<(usize, Tm)> { - let mut oldest_accessed: Option<(usize, Tm)> = None; +fn get_oldest_accessed( + is_secure_cookie: bool, + cookies: &mut Vec<Cookie>, +) -> Option<(usize, SystemTime)> { + let mut oldest_accessed: Option<(usize, SystemTime)> = None; for (i, c) in cookies.iter().enumerate() { if (c.cookie.secure().unwrap_or(false) == is_secure_cookie) && oldest_accessed diff --git a/components/net/fetch/cors_cache.rs b/components/net/fetch/cors_cache.rs index 666a160a591..c2932e07214 100644 --- a/components/net/fetch/cors_cache.rs +++ b/components/net/fetch/cors_cache.rs @@ -9,11 +9,12 @@ //! This library will eventually become the core of the Fetch crate //! with CORSRequest being expanded into FetchRequest (etc) +use std::time::{Duration, SystemTime}; + use http::header::HeaderName; use http::Method; use net_traits::request::{CredentialsMode, Origin, Request}; use servo_url::ServoUrl; -use time::{self, Timespec}; /// Union type for CORS cache entries /// @@ -45,17 +46,17 @@ impl HeaderOrMethod { pub struct CorsCacheEntry { pub origin: Origin, pub url: ServoUrl, - pub max_age: u32, + pub max_age: Duration, pub credentials: bool, pub header_or_method: HeaderOrMethod, - created: Timespec, + created: SystemTime, } impl CorsCacheEntry { fn new( origin: Origin, url: ServoUrl, - max_age: u32, + max_age: Duration, credentials: bool, header_or_method: HeaderOrMethod, ) -> CorsCacheEntry { @@ -65,7 +66,7 @@ impl CorsCacheEntry { max_age: max_age, credentials: credentials, header_or_method: header_or_method, - created: time::now().to_timespec(), + created: SystemTime::now(), } } } @@ -111,10 +112,11 @@ impl CorsCache { /// Remove old entries pub fn cleanup(&mut self) { let CorsCache(buf) = self.clone(); - let now = time::now().to_timespec(); + let now = SystemTime::now(); + let new_buf: Vec<CorsCacheEntry> = buf .into_iter() - .filter(|e| now.sec < e.created.sec + e.max_age as i64) + .filter(|e| now < e.created + e.max_age) .collect(); *self = CorsCache(new_buf); } @@ -133,7 +135,7 @@ impl CorsCache { &mut self, request: &Request, header_name: &HeaderName, - new_max_age: u32, + new_max_age: Duration, ) -> bool { match self .find_entry_by_header(&request, header_name) @@ -167,7 +169,7 @@ impl CorsCache { &mut self, request: &Request, method: Method, - new_max_age: u32, + new_max_age: Duration, ) -> bool { match self .find_entry_by_method(&request, method.clone()) diff --git a/components/net/hsts.rs b/components/net/hsts.rs index 681e754fd76..3c9841a5f78 100644 --- a/components/net/hsts.rs +++ b/components/net/hsts.rs @@ -4,6 +4,7 @@ use std::collections::HashMap; use std::net::{Ipv4Addr, Ipv6Addr}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; use embedder_traits::resources::{self, Resource}; use headers::{HeaderMapExt, StrictTransportSecurity}; @@ -19,7 +20,7 @@ use servo_url::{Host, ServoUrl}; pub struct HstsEntry { pub host: String, pub include_subdomains: bool, - pub max_age: Option<u64>, + pub max_age: Option<Duration>, pub timestamp: Option<u64>, } @@ -27,7 +28,7 @@ impl HstsEntry { pub fn new( host: String, subdomains: IncludeSubdomains, - max_age: Option<u64>, + max_age: Option<Duration>, ) -> Option<HstsEntry> { if host.parse::<Ipv4Addr>().is_ok() || host.parse::<Ipv6Addr>().is_ok() { None @@ -36,7 +37,12 @@ impl HstsEntry { host: host, include_subdomains: (subdomains == IncludeSubdomains::Included), max_age: max_age, - timestamp: Some(time::get_time().sec as u64), + timestamp: Some( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_secs(), + ), }) } } @@ -44,7 +50,11 @@ impl HstsEntry { pub fn is_expired(&self) -> bool { match (self.max_age, self.timestamp) { (Some(max_age), Some(timestamp)) => { - (time::get_time().sec as u64) - timestamp >= max_age + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() - + Duration::from_secs(timestamp) >= + max_age }, _ => false, @@ -196,11 +206,9 @@ impl HstsList { IncludeSubdomains::NotIncluded }; - if let Some(entry) = HstsEntry::new( - host.to_owned(), - include_subdomains, - Some(header.max_age().as_secs()), - ) { + if let Some(entry) = + HstsEntry::new(host.to_owned(), include_subdomains, Some(header.max_age())) + { info!("adding host {} to the strict transport security list", host); info!("- max-age {}", header.max_age().as_secs()); if header.include_subdomains() { diff --git a/components/net/http_cache.rs b/components/net/http_cache.rs index 11d83fe1644..26c47b4723c 100644 --- a/components/net/http_cache.rs +++ b/components/net/http_cache.rs @@ -11,7 +11,7 @@ use std::collections::HashMap; use std::ops::Bound; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Mutex; -use std::time::SystemTime; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; use headers::{ CacheControl, ContentRange, Expires, HeaderMapExt, LastModified, Pragma, Range, Vary, @@ -30,7 +30,6 @@ use net_traits::{FetchMetadata, Metadata, ResourceFetchTiming}; use servo_arc::Arc; use servo_config::pref; use servo_url::ServoUrl; -use time::{Duration, Timespec, Tm}; use tokio::sync::mpsc::{unbounded_channel as unbounded, UnboundedSender as TokioSender}; use crate::fetch::methods::{Data, DoneChannel}; @@ -75,7 +74,7 @@ struct MeasurableCachedResource { raw_status: Option<(u16, Vec<u8>)>, url_list: Vec<ServoUrl>, expires: Duration, - last_validated: Tm, + last_validated: SystemTime, } impl MallocSizeOf for CachedResource { @@ -181,11 +180,11 @@ fn calculate_response_age(response: &Response) -> Duration { if let Some(secs) = response.headers.get(header::AGE) { if let Ok(seconds_string) = secs.to_str() { if let Ok(secs) = seconds_string.parse::<i64>() { - return Duration::seconds(secs); + return Duration::from_secs(secs as u64); } } } - Duration::seconds(0i64) + Duration::ZERO } /// Determine the expiry date from relevant headers, @@ -196,14 +195,10 @@ fn get_response_expiry(response: &Response) -> Duration { if let Some(directives) = response.headers.typed_get::<CacheControl>() { if directives.no_cache() { // Requires validation on first use. - return Duration::seconds(0i64); + return Duration::ZERO; } else { - if let Some(secs) = directives.max_age().or(directives.s_max_age()) { - let max_age = Duration::from_std(secs).unwrap(); - if max_age < age { - return Duration::seconds(0i64); - } - return max_age - age; + if let Some(max_age) = directives.max_age().or(directives.s_max_age()) { + return max_age.checked_sub(age).unwrap_or(Duration::ZERO); } } } @@ -211,18 +206,15 @@ fn get_response_expiry(response: &Response) -> Duration { Some(t) => { // store the period of time from now until expiry let t: SystemTime = t.into(); - let t = t.duration_since(SystemTime::UNIX_EPOCH).unwrap(); - let desired = Timespec::new(t.as_secs() as i64, 0); - let current = time::now().to_timespec(); + let desired = t.duration_since(UNIX_EPOCH).unwrap_or_default(); + let current = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default(); - if desired > current { - return desired - current; - } else { - return Duration::seconds(0i64); - } + return desired.checked_sub(current).unwrap_or(Duration::ZERO); }, // Malformed Expires header, shouldn't be used to construct a valid response. - None if response.headers.contains_key(header::EXPIRES) => return Duration::seconds(0i64), + None if response.headers.contains_key(header::EXPIRES) => return Duration::ZERO, _ => {}, } // Calculating Heuristic Freshness @@ -231,19 +223,18 @@ fn get_response_expiry(response: &Response) -> Duration { // <https://tools.ietf.org/html/rfc7234#section-5.5.4> // Since presently we do not generate a Warning header field with a 113 warn-code, // 24 hours minus response age is the max for heuristic calculation. - let max_heuristic = Duration::hours(24) - age; + let max_heuristic = Duration::from_secs(24 * 3600) - age; let heuristic_freshness = if let Some(last_modified) = // If the response has a Last-Modified header field, // caches are encouraged to use a heuristic expiration value // that is no more than some fraction of the interval since that time. response.headers.typed_get::<LastModified>() { - let current = time::now().to_timespec(); + let current = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default(); let last_modified: SystemTime = last_modified.into(); - let last_modified = last_modified - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap(); - let last_modified = Timespec::new(last_modified.as_secs() as i64, 0); + let last_modified = last_modified.duration_since(UNIX_EPOCH).unwrap(); // A typical setting of this fraction might be 10%. let raw_heuristic_calc = (current - last_modified) / 10; let result = if raw_heuristic_calc < max_heuristic { @@ -268,7 +259,7 @@ fn get_response_expiry(response: &Response) -> Duration { } } // Requires validation upon first use as default. - Duration::seconds(0i64) + Duration::ZERO } /// Request Cache-Control Directives @@ -280,24 +271,19 @@ fn get_expiry_adjustment_from_request_headers(request: &Request, expires: Durati }; if let Some(max_age) = directive.max_stale() { - return expires + Duration::from_std(max_age).unwrap(); + return expires + max_age; } if let Some(max_age) = directive.max_age() { - let max_age = Duration::from_std(max_age).unwrap(); if expires > max_age { - return Duration::min_value(); + return Duration::ZERO; } return expires - max_age; } if let Some(min_fresh) = directive.min_fresh() { - let min_fresh = Duration::from_std(min_fresh).unwrap(); - if expires < min_fresh { - return Duration::min_value(); - } - return expires - min_fresh; + return expires.checked_sub(min_fresh).unwrap_or(Duration::ZERO); } if directive.no_cache() || directive.no_store() { - return Duration::min_value(); + return Duration::ZERO; } expires @@ -341,8 +327,15 @@ fn create_cached_response( response.aborted = cached_resource.aborted.clone(); let expires = cached_resource.data.expires; let adjusted_expires = get_expiry_adjustment_from_request_headers(request, expires); - let now = Duration::seconds(time::now().to_timespec().sec); - let last_validated = Duration::seconds(cached_resource.data.last_validated.to_timespec().sec); + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default(); + let last_validated = cached_resource + .data + .last_validated + .duration_since(UNIX_EPOCH) + .unwrap_or_default(); + let time_since_validated = now - last_validated; // TODO: take must-revalidate into account <https://tools.ietf.org/html/rfc7234#section-5.2.2.1> // TODO: if this cache is to be considered shared, take proxy-revalidate into account @@ -813,7 +806,7 @@ impl HttpCache { let entry_key = CacheKey::from_servo_url(url); if let Some(cached_resources) = self.entries.get_mut(&entry_key) { for cached_resource in cached_resources.iter_mut() { - cached_resource.data.expires = Duration::seconds(0i64); + cached_resource.data.expires = Duration::ZERO; } } } @@ -897,7 +890,7 @@ impl HttpCache { raw_status: response.raw_status.clone(), url_list: response.url_list.clone(), expires: expiry, - last_validated: time::now(), + last_validated: SystemTime::now(), }), }; let entry = self.entries.entry(entry_key).or_insert_with(|| vec![]); diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index 17f12b13c1b..7b953bc3a14 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -122,7 +122,10 @@ impl HttpState { } fn precise_time_ms() -> u64 { - time::precise_time_ns() / (1000 * 1000) + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as u64 } // Step 3 of https://fetch.spec.whatwg.org/#concept-fetch. @@ -2108,7 +2111,6 @@ async fn cors_preflight_fetch( .typed_get::<AccessControlMaxAge>() .map(|acma| acma.into()) .unwrap_or(Duration::from_secs(5)); - let max_age = max_age.as_secs() as u32; // Substep 10 // TODO: Need to define what an imposed limit on max-age is diff --git a/components/net/tests/hsts.rs b/components/net/tests/hsts.rs index a3bebb67fcf..ecd94e2fc68 100644 --- a/components/net/tests/hsts.rs +++ b/components/net/tests/hsts.rs @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::collections::HashMap; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; use net::hsts::{HstsEntry, HstsList}; use net_traits::IncludeSubdomains; @@ -12,7 +13,7 @@ fn test_hsts_entry_is_not_expired_when_it_has_no_timestamp() { let entry = HstsEntry { host: "mozilla.org".to_owned(), include_subdomains: false, - max_age: Some(20), + max_age: Some(Duration::from_secs(20)), timestamp: None, }; @@ -25,7 +26,12 @@ fn test_hsts_entry_is_not_expired_when_it_has_no_max_age() { host: "mozilla.org".to_owned(), include_subdomains: false, max_age: None, - timestamp: Some(time::get_time().sec as u64), + timestamp: Some( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_secs(), + ), }; assert!(!entry.is_expired()); @@ -36,8 +42,14 @@ fn test_hsts_entry_is_expired_when_it_has_reached_its_max_age() { let entry = HstsEntry { host: "mozilla.org".to_owned(), include_subdomains: false, - max_age: Some(10), - timestamp: Some(time::get_time().sec as u64 - 20u64), + max_age: Some(Duration::from_secs(10)), + timestamp: Some( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_secs() - + 20u64, + ), }; assert!(entry.is_expired()); @@ -106,7 +118,7 @@ fn test_push_entry_with_0_max_age_evicts_entry_from_list() { vec![HstsEntry::new( "mozilla.org".to_owned(), IncludeSubdomains::NotIncluded, - Some(500000u64), + Some(Duration::from_secs(500000u64)), ) .unwrap()], ); @@ -118,7 +130,7 @@ fn test_push_entry_with_0_max_age_evicts_entry_from_list() { HstsEntry::new( "mozilla.org".to_owned(), IncludeSubdomains::NotIncluded, - Some(0), + Some(Duration::ZERO), ) .unwrap(), ); @@ -367,8 +379,14 @@ fn test_hsts_list_with_expired_entry_is_not_is_host_secure() { vec![HstsEntry { host: "mozilla.org".to_owned(), include_subdomains: false, - max_age: Some(20), - timestamp: Some(time::get_time().sec as u64 - 100u64), + max_age: Some(Duration::from_secs(20)), + timestamp: Some( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_secs() - + 100u64, + ), }], ); let hsts_list = HstsList { |