mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Add PerformanceResourceTiming: TimingAllowCheck
The purpose of this commit is to implement https://w3c.github.io/resource-timing/#dfn-timing-allow-check
This commit is contained in:
parent
4159f01feb
commit
bb8166bb97
2 changed files with 50 additions and 3 deletions
|
@ -37,6 +37,7 @@ use hyper::{Body, Client, Method, Response as HyperResponse, StatusCode};
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
use msg::constellation_msg::{HistoryStateId, PipelineId};
|
use msg::constellation_msg::{HistoryStateId, PipelineId};
|
||||||
use net_traits::quality::{quality_to_value, Quality, QualityItem};
|
use net_traits::quality::{quality_to_value, Quality, QualityItem};
|
||||||
|
use net_traits::request::Origin::Origin as SpecificOrigin;
|
||||||
use net_traits::request::{CacheMode, CredentialsMode, Destination, Origin};
|
use net_traits::request::{CacheMode, CredentialsMode, Destination, Origin};
|
||||||
use net_traits::request::{RedirectMode, Referrer, Request, RequestMode};
|
use net_traits::request::{RedirectMode, Referrer, Request, RequestMode};
|
||||||
use net_traits::request::{ResponseTainting, ServiceWorkersMode};
|
use net_traits::request::{ResponseTainting, ServiceWorkersMode};
|
||||||
|
@ -44,6 +45,7 @@ use net_traits::response::{HttpsState, Response, ResponseBody, ResponseType};
|
||||||
use net_traits::{CookieSource, FetchMetadata, NetworkError, ReferrerPolicy};
|
use net_traits::{CookieSource, FetchMetadata, NetworkError, ReferrerPolicy};
|
||||||
use net_traits::{RedirectEndValue, RedirectStartValue, ResourceAttribute, ResourceFetchTiming};
|
use net_traits::{RedirectEndValue, RedirectStartValue, ResourceAttribute, ResourceFetchTiming};
|
||||||
use openssl::ssl::SslConnectorBuilder;
|
use openssl::ssl::SslConnectorBuilder;
|
||||||
|
use servo_arc::Arc;
|
||||||
use servo_url::{ImmutableOrigin, ServoUrl};
|
use servo_url::{ImmutableOrigin, ServoUrl};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
@ -51,7 +53,7 @@ use std::iter::FromIterator;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
use std::sync::{Mutex, RwLock};
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
use time::{self, Tm};
|
use time::{self, Tm};
|
||||||
use tokio::prelude::{future, Future, Stream};
|
use tokio::prelude::{future, Future, Stream};
|
||||||
|
@ -631,7 +633,7 @@ pub fn http_fetch(
|
||||||
request.redirect_count as u16,
|
request.redirect_count as u16,
|
||||||
));
|
));
|
||||||
|
|
||||||
response.resource_timing = context.timing.lock().unwrap().clone();
|
response.resource_timing = Arc::clone(&context.timing);
|
||||||
|
|
||||||
// Step 6
|
// Step 6
|
||||||
response
|
response
|
||||||
|
@ -828,7 +830,6 @@ fn http_network_or_cache_fetch(
|
||||||
) -> Response {
|
) -> Response {
|
||||||
// Step 2
|
// Step 2
|
||||||
let mut response: Option<Response> = None;
|
let mut response: Option<Response> = None;
|
||||||
|
|
||||||
// Step 4
|
// Step 4
|
||||||
let mut revalidating_flag = false;
|
let mut revalidating_flag = false;
|
||||||
|
|
||||||
|
@ -1302,8 +1303,32 @@ fn http_network_fetch(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let header_strings: Vec<&str> = res
|
||||||
|
.headers()
|
||||||
|
.get_all("Timing-Allow-Origin")
|
||||||
|
.iter()
|
||||||
|
.map(|header_value| header_value.to_str().unwrap_or(""))
|
||||||
|
.collect();
|
||||||
|
let wildcard_present = header_strings.iter().any(|header_str| *header_str == "*");
|
||||||
|
// The spec: https://www.w3.org/TR/resource-timing-2/#sec-timing-allow-origin
|
||||||
|
// says that a header string is either an origin or a wildcard so we can just do a straight
|
||||||
|
// check against the document origin
|
||||||
|
let req_origin_in_timing_allow = header_strings
|
||||||
|
.iter()
|
||||||
|
.any(|header_str| match request.origin {
|
||||||
|
SpecificOrigin(ref immutable_request_origin) => {
|
||||||
|
*header_str == immutable_request_origin.ascii_serialization()
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if !req_origin_in_timing_allow && !wildcard_present {
|
||||||
|
context.timing.lock().unwrap().mark_timing_check_failed();
|
||||||
|
}
|
||||||
|
|
||||||
let timing = context.timing.lock().unwrap().clone();
|
let timing = context.timing.lock().unwrap().clone();
|
||||||
let mut response = Response::new(url.clone(), timing);
|
let mut response = Response::new(url.clone(), timing);
|
||||||
|
|
||||||
response.status = Some((
|
response.status = Some((
|
||||||
res.status(),
|
res.status(),
|
||||||
res.status().canonical_reason().unwrap_or("").into(),
|
res.status().canonical_reason().unwrap_or("").into(),
|
||||||
|
|
|
@ -232,6 +232,8 @@ impl FetchTaskTarget for IpcSender<FetchResponseMsg> {
|
||||||
} else {
|
} else {
|
||||||
let _ = self.send(FetchResponseMsg::ProcessResponseEOF(Ok(response
|
let _ = self.send(FetchResponseMsg::ProcessResponseEOF(Ok(response
|
||||||
.get_resource_timing()
|
.get_resource_timing()
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
.clone())));
|
.clone())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -459,6 +461,7 @@ pub struct ResourceCorsData {
|
||||||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
|
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
|
||||||
pub struct ResourceFetchTiming {
|
pub struct ResourceFetchTiming {
|
||||||
pub domain_lookup_start: u64,
|
pub domain_lookup_start: u64,
|
||||||
|
pub timing_check_passed: bool,
|
||||||
pub timing_type: ResourceTimingType,
|
pub timing_type: ResourceTimingType,
|
||||||
/// Number of redirects until final resource (currently limited to 20)
|
/// Number of redirects until final resource (currently limited to 20)
|
||||||
pub redirect_count: u16,
|
pub redirect_count: u16,
|
||||||
|
@ -508,6 +511,7 @@ impl ResourceFetchTiming {
|
||||||
pub fn new(timing_type: ResourceTimingType) -> ResourceFetchTiming {
|
pub fn new(timing_type: ResourceTimingType) -> ResourceFetchTiming {
|
||||||
ResourceFetchTiming {
|
ResourceFetchTiming {
|
||||||
timing_type: timing_type,
|
timing_type: timing_type,
|
||||||
|
timing_check_passed: true,
|
||||||
domain_lookup_start: 0,
|
domain_lookup_start: 0,
|
||||||
redirect_count: 0,
|
redirect_count: 0,
|
||||||
request_start: 0,
|
request_start: 0,
|
||||||
|
@ -524,6 +528,13 @@ impl ResourceFetchTiming {
|
||||||
// TODO currently this is being set with precise time ns when it should be time since
|
// TODO currently this is being set with precise time ns when it should be time since
|
||||||
// time origin (as described in Performance::now)
|
// time origin (as described in Performance::now)
|
||||||
pub fn set_attribute(&mut self, attribute: ResourceAttribute) {
|
pub fn set_attribute(&mut self, attribute: ResourceAttribute) {
|
||||||
|
let should_attribute_always_be_updated = match attribute {
|
||||||
|
ResourceAttribute::FetchStart | ResourceAttribute::ResponseEnd => true,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
if !self.timing_check_passed && !should_attribute_always_be_updated {
|
||||||
|
return;
|
||||||
|
}
|
||||||
match attribute {
|
match attribute {
|
||||||
ResourceAttribute::DomainLookupStart => self.domain_lookup_start = precise_time_ns(),
|
ResourceAttribute::DomainLookupStart => self.domain_lookup_start = precise_time_ns(),
|
||||||
ResourceAttribute::RedirectCount(count) => self.redirect_count = count,
|
ResourceAttribute::RedirectCount(count) => self.redirect_count = count,
|
||||||
|
@ -547,6 +558,17 @@ impl ResourceFetchTiming {
|
||||||
ResourceAttribute::ResponseEnd => self.response_end = precise_time_ns(),
|
ResourceAttribute::ResponseEnd => self.response_end = precise_time_ns(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mark_timing_check_failed(&mut self) {
|
||||||
|
self.timing_check_passed = false;
|
||||||
|
self.domain_lookup_start = 0;
|
||||||
|
self.redirect_count = 0;
|
||||||
|
self.request_start = 0;
|
||||||
|
self.response_start = 0;
|
||||||
|
self.redirect_start = 0;
|
||||||
|
self.connect_start = 0;
|
||||||
|
self.connect_end = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Metadata about a loaded resource, such as is obtained from HTTP headers.
|
/// Metadata about a loaded resource, such as is obtained from HTTP headers.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue