net: Stop using both versions of the time crate in the cookie code (#33260)

`std::time` is good enough for us here. `cookie` is using `time 0.3`,
but Servo can convert to standard library types when getting data from
`cookie`. This reduces our direct dependencies and removes more use of
the very old `time 0.1` series.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2024-08-30 19:15:47 +02:00 committed by GitHub
parent 1e9344cb5c
commit 6f333a8e29
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 29 additions and 95 deletions

4
Cargo.lock generated
View file

@ -1277,7 +1277,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [ dependencies = [
"powerfmt", "powerfmt",
"serde",
] ]
[[package]] [[package]]
@ -2967,8 +2966,6 @@ dependencies = [
"serde", "serde",
"serde_bytes", "serde_bytes",
"serde_test", "serde_test",
"time 0.1.45",
"time 0.3.36",
] ]
[[package]] [[package]]
@ -4518,7 +4515,6 @@ dependencies = [
"servo_url", "servo_url",
"sha2", "sha2",
"time 0.1.45", "time 0.1.45",
"time 0.3.36",
"tokio", "tokio",
"tokio-rustls", "tokio-rustls",
"tokio-stream", "tokio-stream",

View file

@ -121,7 +121,6 @@ syn = { version = "2", default-features = false, features = ["clone-impls", "der
synstructure = "0.13" synstructure = "0.13"
thin-vec = "0.2.13" thin-vec = "0.2.13"
time = "0.1.41" time = "0.1.41"
time_03 = { package = "time", version = "0.3", features = ["serde"] }
to_shmem = { git = "https://github.com/servo/stylo", branch = "2024-07-16" } to_shmem = { git = "https://github.com/servo/stylo", branch = "2024-07-16" }
tokio = "1" tokio = "1"
tokio-rustls = "0.24" tokio-rustls = "0.24"

View file

@ -23,8 +23,6 @@ hyper = { workspace = true }
mime = { workspace = true } mime = { workspace = true }
serde = { workspace = true } serde = { workspace = true }
serde_bytes = { workspace = true } serde_bytes = { workspace = true }
time = { workspace = true }
time_03 = { workspace = true }
[dev-dependencies] [dev-dependencies]
serde_test = "1.0" serde_test = "1.0"

View file

@ -20,7 +20,6 @@
//! * `hyper::Method` //! * `hyper::Method`
//! * `hyper::Uri` //! * `hyper::Uri`
//! * `mime::Mime` //! * `mime::Mime`
//! * `time::Tm`
//! //!
//! # How do I use a data type with a `HeaderMap` member with Serde? //! # How do I use a data type with a `HeaderMap` member with Serde?
//! //!
@ -78,7 +77,6 @@ use serde::de::{self, Error, MapAccess, SeqAccess, Visitor};
use serde::ser::{SerializeMap, SerializeSeq}; use serde::ser::{SerializeMap, SerializeSeq};
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_bytes::{ByteBuf, Bytes}; use serde_bytes::{ByteBuf, Bytes};
use time::{strptime, Tm};
/// Deserialises a `T` value with a given deserializer. /// Deserialises a `T` value with a given deserializer.
/// ///
@ -604,43 +602,6 @@ impl<'de> Visitor<'de> for StatusVisitor {
} }
} }
impl<'de> Deserialize<'de> for De<Tm> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct TmVisitor;
impl<'de> Visitor<'de> for TmVisitor {
type Value = De<Tm>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a date and time according to RFC 3339")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
strptime(v, "%Y-%m-%dT%H:%M:%SZ")
.map(De::new)
.map_err(|e| E::custom(e.to_string()))
}
}
deserializer.deserialize_string(TmVisitor)
}
}
impl<'a> Serialize for Ser<'a, Tm> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.v.rfc3339().to_string())
}
}
impl<'de> Deserialize<'de> for De<Uri> { impl<'de> Deserialize<'de> for De<Uri> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where

View file

@ -15,7 +15,6 @@ use hyper::{Method, StatusCode, Uri};
use hyper_serde::{De, Ser, Serde}; use hyper_serde::{De, Ser, Serde};
use mime::Mime; use mime::Mime;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use time::Tm;
fn is_supported<T>() fn is_supported<T>()
where where
@ -33,6 +32,5 @@ fn supported() {
is_supported::<Method>(); is_supported::<Method>();
is_supported::<Mime>(); is_supported::<Mime>();
is_supported::<StatusCode>(); is_supported::<StatusCode>();
is_supported::<Tm>();
is_supported::<Uri>(); is_supported::<Uri>();
} }

View file

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use std::time::Duration;
use cookie::{Cookie, CookieBuilder}; use cookie::{Cookie, CookieBuilder};
use headers::ContentType; use headers::ContentType;
use http::header::{self, HeaderMap, HeaderValue}; use http::header::{self, HeaderMap, HeaderValue};
@ -15,7 +17,6 @@ use http::StatusCode;
use hyper::{Method, Uri}; use hyper::{Method, Uri};
use hyper_serde::{De, Ser}; use hyper_serde::{De, Ser};
use serde_test::{assert_de_tokens, assert_ser_tokens, Token}; use serde_test::{assert_de_tokens, assert_ser_tokens, Token};
use time_03::Duration;
#[test] #[test]
fn test_content_type() { fn test_content_type() {
@ -32,7 +33,7 @@ fn test_cookie() {
// string with a bunch of indices in it which apparently is different from the exact same // string with a bunch of indices in it which apparently is different from the exact same
// cookie but parsed as a bunch of strings. // cookie but parsed as a bunch of strings.
let cookie: Cookie = CookieBuilder::new("Hello", "World!") let cookie: Cookie = CookieBuilder::new("Hello", "World!")
.max_age(Duration::seconds(42)) .max_age(Duration::from_secs(42).try_into().unwrap_or_default())
.domain("servo.org") .domain("servo.org")
.path("/") .path("/")
.secure(true) .secure(true)
@ -111,17 +112,6 @@ fn test_raw_status() {
assert_de_tokens(&De::new(raw_status), tokens); assert_de_tokens(&De::new(raw_status), tokens);
} }
#[test]
fn test_tm() {
use time::strptime;
let time = strptime("2017-02-22T12:03:31Z", "%Y-%m-%dT%H:%M:%SZ").unwrap();
let tokens = &[Token::Str("2017-02-22T12:03:31Z")];
assert_ser_tokens(&Ser::new(&time), tokens);
assert_de_tokens(&De::new(time), tokens);
}
#[test] #[test]
fn test_uri() { fn test_uri() {
use std::str::FromStr; use std::str::FromStr;

View file

@ -57,7 +57,6 @@ servo_config = { path = "../config" }
servo_url = { path = "../url" } servo_url = { path = "../url" }
sha2 = "0.10" sha2 = "0.10"
time = { workspace = true } time = { workspace = true }
time_03 = { workspace = true }
chrono = { workspace = true } chrono = { workspace = true }
tokio = { workspace = true, features = ["sync", "macros", "rt-multi-thread"] } tokio = { workspace = true, features = ["sync", "macros", "rt-multi-thread"] }
tokio-rustls = { workspace = true } tokio-rustls = { workspace = true }

View file

@ -7,14 +7,13 @@
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::net::{Ipv4Addr, Ipv6Addr}; use std::net::{Ipv4Addr, Ipv6Addr};
use std::time::{Duration, SystemTime};
use cookie::Cookie; use cookie::Cookie;
use net_traits::pub_domains::is_pub_domain; use net_traits::pub_domains::is_pub_domain;
use net_traits::CookieSource; use net_traits::CookieSource;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use servo_url::ServoUrl; use servo_url::ServoUrl;
use time::{now, Tm};
use time_03::OffsetDateTime;
/// A stored cookie that wraps the definition in cookie-rs. This is used to implement /// 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, /// various behaviours defined in the spec that rely on an associated request URL,
@ -28,17 +27,9 @@ pub struct ServoCookie {
pub cookie: Cookie<'static>, pub cookie: Cookie<'static>,
pub host_only: bool, pub host_only: bool,
pub persistent: bool, pub persistent: bool,
#[serde( pub creation_time: SystemTime,
deserialize_with = "hyper_serde::deserialize", pub last_access: SystemTime,
serialize_with = "hyper_serde::serialize" pub expiry_time: Option<SystemTime>,
)]
pub creation_time: Tm,
#[serde(
deserialize_with = "hyper_serde::deserialize",
serialize_with = "hyper_serde::serialize"
)]
pub last_access: Tm,
pub expiry_time: Option<OffsetDateTime>,
} }
impl ServoCookie { impl ServoCookie {
@ -60,9 +51,11 @@ impl ServoCookie {
source: CookieSource, source: CookieSource,
) -> Option<ServoCookie> { ) -> Option<ServoCookie> {
// Step 3 // Step 3
let (persistent, expiry_time) = match (cookie.max_age(), cookie.expires_datetime()) { let max_age: Option<Duration> =
(Some(max_age), _) => (true, Some(time_03::OffsetDateTime::now_utc() + max_age)), cookie.max_age().and_then(|max_age| max_age.try_into().ok());
(_, Some(date_time)) => (true, Some(date_time)), let (persistent, expiry_time) = match (max_age, cookie.expires_datetime()) {
(Some(max_age), _) => (true, Some(SystemTime::now() + max_age)),
(_, Some(date_time)) => (true, Some(date_time.into())),
_ => (false, None), _ => (false, None),
}; };
@ -131,18 +124,18 @@ impl ServoCookie {
cookie, cookie,
host_only, host_only,
persistent, persistent,
creation_time: now(), creation_time: SystemTime::now(),
last_access: now(), last_access: SystemTime::now(),
expiry_time, expiry_time,
}) })
} }
pub fn touch(&mut self) { pub fn touch(&mut self) {
self.last_access = now(); self.last_access = SystemTime::now();
} }
pub fn set_expiry_time_in_past(&mut self) { pub fn set_expiry_time_in_past(&mut self) {
self.expiry_time = Some(time_03::OffsetDateTime::UNIX_EPOCH); self.expiry_time = Some(SystemTime::UNIX_EPOCH)
} }
// http://tools.ietf.org/html/rfc6265#section-5.1.4 // http://tools.ietf.org/html/rfc6265#section-5.1.4

View file

@ -8,14 +8,13 @@
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::collections::HashMap; use std::collections::HashMap;
use std::time::SystemTime;
use log::{debug, info}; use log::{debug, info};
use net_traits::pub_domains::reg_suffix; use net_traits::pub_domains::reg_suffix;
use net_traits::CookieSource; use net_traits::CookieSource;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use servo_url::ServoUrl; use servo_url::ServoUrl;
use time::Tm;
use time_03::OffsetDateTime;
use crate::cookie::ServoCookie; use crate::cookie::ServoCookie;
@ -145,11 +144,7 @@ impl CookieStorage {
let a_path_len = a.cookie.path().as_ref().map_or(0, |p| p.len()); let a_path_len = a.cookie.path().as_ref().map_or(0, |p| p.len());
let b_path_len = b.cookie.path().as_ref().map_or(0, |p| p.len()); let b_path_len = b.cookie.path().as_ref().map_or(0, |p| p.len());
match a_path_len.cmp(&b_path_len) { match a_path_len.cmp(&b_path_len) {
Ordering::Equal => { Ordering::Equal => a.creation_time.cmp(&b.creation_time),
let a_creation_time = a.creation_time.to_timespec();
let b_creation_time = b.creation_time.to_timespec();
a_creation_time.cmp(&b_creation_time)
},
// Ensure that longer paths are sorted earlier than shorter paths // Ensure that longer paths are sorted earlier than shorter paths
Ordering::Greater => Ordering::Less, Ordering::Greater => Ordering::Less,
Ordering::Less => Ordering::Greater, Ordering::Less => Ordering::Greater,
@ -235,12 +230,12 @@ fn reg_host(url: &str) -> String {
} }
fn is_cookie_expired(cookie: &ServoCookie) -> bool { fn is_cookie_expired(cookie: &ServoCookie) -> bool {
matches!(cookie.expiry_time, Some(date_time) if date_time <= OffsetDateTime::now_utc()) matches!(cookie.expiry_time, Some(date_time) if date_time <= SystemTime::now())
} }
fn evict_one_cookie(is_secure_cookie: bool, cookies: &mut Vec<ServoCookie>) -> bool { fn evict_one_cookie(is_secure_cookie: bool, cookies: &mut Vec<ServoCookie>) -> bool {
// Remove non-secure cookie with oldest access time // 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 { if let Some((index, _)) = oldest_accessed {
cookies.remove(index); cookies.remove(index);
@ -249,7 +244,7 @@ fn evict_one_cookie(is_secure_cookie: bool, cookies: &mut Vec<ServoCookie>) -> b
if !is_secure_cookie { if !is_secure_cookie {
return false; return false;
} }
let oldest_accessed: Option<(usize, Tm)> = get_oldest_accessed(true, cookies); let oldest_accessed = get_oldest_accessed(true, cookies);
if let Some((index, _)) = oldest_accessed { if let Some((index, _)) = oldest_accessed {
cookies.remove(index); cookies.remove(index);
} }
@ -257,13 +252,18 @@ fn evict_one_cookie(is_secure_cookie: bool, cookies: &mut Vec<ServoCookie>) -> b
true true
} }
fn get_oldest_accessed(is_secure_cookie: bool, cookies: &mut [ServoCookie]) -> Option<(usize, Tm)> { fn get_oldest_accessed(
let mut oldest_accessed: Option<(usize, Tm)> = None; is_secure_cookie: bool,
cookies: &mut [ServoCookie],
) -> Option<(usize, SystemTime)> {
let mut oldest_accessed = None;
for (i, c) in cookies.iter().enumerate() { for (i, c) in cookies.iter().enumerate() {
if (c.cookie.secure().unwrap_or(false) == is_secure_cookie) && if (c.cookie.secure().unwrap_or(false) == is_secure_cookie) &&
oldest_accessed oldest_accessed
.as_ref() .as_ref()
.map_or(true, |a| c.last_access < a.1) .map_or(true, |(_, current_oldest_time)| {
c.last_access < *current_oldest_time
})
{ {
oldest_accessed = Some((i, c.last_access)); oldest_accessed = Some((i, c.last_access));
} }