Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PerformanceResourceTiming:TimingAllowCheck #23873

Merged
merged 4 commits into from Sep 25, 2019
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -23,6 +23,7 @@ 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 servo_arc::Arc as ServoArc;
use servo_url::ServoUrl;
use std::borrow::Cow;
use std::fs::File;
@@ -52,7 +53,7 @@ pub struct FetchContext {
pub devtools_chan: Option<Sender<DevtoolsControlMsg>>,
pub filemanager: FileManager,
pub cancellation_listener: Arc<Mutex<CancellationListener>>,
pub timing: Arc<Mutex<ResourceFetchTiming>>,
pub timing: ServoArc<Mutex<ResourceFetchTiming>>,
}

pub struct CancellationListener {
@@ -37,21 +37,23 @@ use hyper::{Body, Client, Method, Response as HyperResponse, StatusCode};
use hyper_serde::Serde;
use msg::constellation_msg::{HistoryStateId, PipelineId};
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::{RedirectMode, Referrer, Request, RequestMode};
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 openssl::ssl::SslConnectorBuilder;
use servo_arc::Arc;
use servo_url::{ImmutableOrigin, ServoUrl};
use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::iter::FromIterator;
use std::mem;
use std::ops::Deref;
use std::str::FromStr;
use std::sync::{Arc, Mutex, RwLock};
use std::sync::{Mutex, RwLock};
use std::time::{Duration, SystemTime};
use time::{self, Tm};
use tokio::prelude::{future, Future, Stream};
@@ -631,7 +633,7 @@ pub fn http_fetch(
request.redirect_count as u16,
));

response.resource_timing = context.timing.lock().unwrap().clone();
response.resource_timing = Arc::clone(&context.timing);

// Step 6
response
@@ -828,7 +830,6 @@ fn http_network_or_cache_fetch(
) -> Response {
// Step 2
let mut response: Option<Response> = None;

// Step 4
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 mut response = Response::new(url.clone(), timing);

response.status = Some((
res.status(),
res.status().canonical_reason().unwrap_or("").into(),
@@ -36,6 +36,7 @@ use profile_traits::mem::ProfilerChan as MemProfilerChan;
use profile_traits::mem::{Report, ReportKind, ReportsChan};
use profile_traits::time::ProfilerChan;
use serde::{Deserialize, Serialize};
use servo_arc::Arc as ServoArc;
use servo_url::ServoUrl;
use std::borrow::{Cow, ToOwned};
use std::collections::HashMap;
@@ -491,7 +492,7 @@ impl CoreResourceManager {
devtools_chan: dc,
filemanager: filemanager,
cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(cancel_chan))),
timing: Arc::new(Mutex::new(ResourceFetchTiming::new(request.timing_type()))),
timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new(request.timing_type()))),
};

match res_init_ {
@@ -36,6 +36,7 @@ use net_traits::{
FetchTaskTarget, IncludeSubdomains, NetworkError, ReferrerPolicy, ResourceFetchTiming,
ResourceTimingType,
};
use servo_arc::Arc as ServoArc;
use servo_url::{ImmutableOrigin, ServoUrl};
use std::fs::File;
use std::io::Read;
@@ -665,7 +666,7 @@ fn test_fetch_with_hsts() {
devtools_chan: None,
filemanager: FileManager::new(create_embedder_proxy()),
cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(None))),
timing: Arc::new(Mutex::new(ResourceFetchTiming::new(
timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new(
ResourceTimingType::Navigation,
))),
};
@@ -38,6 +38,7 @@ use net_traits::request::Request;
use net_traits::response::Response;
use net_traits::{FetchTaskTarget, ResourceFetchTiming, ResourceTimingType};
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use servo_arc::Arc as ServoArc;
use servo_url::ServoUrl;
use std::net::TcpListener as StdTcpListener;
use std::path::PathBuf;
@@ -95,7 +96,7 @@ fn new_fetch_context(
devtools_chan: dc,
filemanager: FileManager::new(sender),
cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(None))),
timing: Arc::new(Mutex::new(ResourceFetchTiming::new(
timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new(
ResourceTimingType::Navigation,
))),
}
@@ -232,6 +232,8 @@ impl FetchTaskTarget for IpcSender<FetchResponseMsg> {
} else {
let _ = self.send(FetchResponseMsg::ProcessResponseEOF(Ok(response
.get_resource_timing()
.lock()
.unwrap()
.clone())));
}
}
@@ -459,6 +461,7 @@ pub struct ResourceCorsData {
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
pub struct ResourceFetchTiming {
pub domain_lookup_start: u64,
pub timing_check_passed: bool,
pub timing_type: ResourceTimingType,
/// Number of redirects until final resource (currently limited to 20)
pub redirect_count: u16,
@@ -508,6 +511,7 @@ impl ResourceFetchTiming {
pub fn new(timing_type: ResourceTimingType) -> ResourceFetchTiming {
ResourceFetchTiming {
timing_type: timing_type,
timing_check_passed: true,
domain_lookup_start: 0,
redirect_count: 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
// 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,
_ => false,
};
if !self.timing_check_passed && !should_attribute_always_be_updated {
return;
}
match attribute {
ResourceAttribute::DomainLookupStart => self.domain_lookup_start = precise_time_ns(),
ResourceAttribute::RedirectCount(count) => self.redirect_count = count,
@@ -547,6 +558,17 @@ impl ResourceFetchTiming {
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.
@@ -114,7 +114,8 @@ pub struct Response {
#[ignore_malloc_size_of = "AtomicBool heap size undefined"]
pub aborted: Arc<AtomicBool>,
/// track network metrics
pub resource_timing: ResourceFetchTiming,
#[ignore_malloc_size_of = "Mutex heap size undefined"]
pub resource_timing: Arc<Mutex<ResourceFetchTiming>>,
}

impl Response {
@@ -137,7 +138,7 @@ impl Response {
internal_response: None,
return_internal: true,
aborted: Arc::new(AtomicBool::new(false)),
resource_timing: resource_timing,
resource_timing: Arc::new(Mutex::new(resource_timing)),
}
}

@@ -171,7 +172,9 @@ impl Response {
internal_response: None,
return_internal: true,
aborted: Arc::new(AtomicBool::new(false)),
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Error),
resource_timing: Arc::new(Mutex::new(ResourceFetchTiming::new(
ResourceTimingType::Error,
))),
}
}

@@ -217,8 +220,8 @@ impl Response {
}
}

pub fn get_resource_timing(&self) -> &ResourceFetchTiming {
&self.resource_timing
pub fn get_resource_timing(&self) -> Arc<Mutex<ResourceFetchTiming>> {
Arc::clone(&self.resource_timing)
}

/// Convert to a filtered response, of type `filter_type`.
@@ -50,9 +50,9 @@ pub struct PerformanceResourceTiming {
request_start: f64,
response_start: f64,
response_end: f64,
// transfer_size: f64, //size in octets
// encoded_body_size: f64, //size in octets
// decoded_body_size: f64, //size in octets
transfer_size: u64, //size in octets
encoded_body_size: u64, //size in octets
decoded_body_size: u64, //size in octets
}

// TODO(#21254): startTime
@@ -71,10 +71,15 @@ impl PerformanceResourceTiming {
next_hop: Option<DOMString>,
fetch_start: f64,
) -> PerformanceResourceTiming {
let entry_type = if initiator_type == InitiatorType::Navigation {
DOMString::from("navigation")
} else {
DOMString::from("resource")
};
PerformanceResourceTiming {
entry: PerformanceEntry::new_inherited(
DOMString::from(url.into_string()),
DOMString::from("resource"),
entry_type,
0.,
0.,
),
@@ -92,6 +97,9 @@ impl PerformanceResourceTiming {
request_start: 0.,
response_start: 0.,
response_end: 0.,
transfer_size: 0,

This comment has been minimized.

@jdm

jdm Sep 16, 2019

Member

Looking at this code made me file #24218.

encoded_body_size: 0,
decoded_body_size: 0,
}
}

@@ -117,13 +125,18 @@ impl PerformanceResourceTiming {
redirect_end: resource_timing.redirect_end as f64,
fetch_start: resource_timing.fetch_start as f64,
domain_lookup_start: resource_timing.domain_lookup_start as f64,
//TODO (#21260)
domain_lookup_end: 0.,
connect_start: resource_timing.connect_start as f64,
connect_end: resource_timing.connect_end as f64,
// TODO (#21271)
secure_connection_start: 0.,
request_start: resource_timing.request_start as f64,
response_start: resource_timing.response_start as f64,
response_end: resource_timing.response_end as f64,
transfer_size: 0,
encoded_body_size: 0,
decoded_body_size: 0,
}
}

@@ -175,6 +188,31 @@ impl PerformanceResourceTimingMethods for PerformanceResourceTiming {
Finite::wrap(self.domain_lookup_start)
}

// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-domainlookupend
fn DomainLookupEnd(&self) -> DOMHighResTimeStamp {
Finite::wrap(self.domain_lookup_end)
}

// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-secureconnectionstart
fn SecureConnectionStart(&self) -> DOMHighResTimeStamp {
Finite::wrap(self.secure_connection_start)
}

// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-transfersize
fn TransferSize(&self) -> u64 {
self.transfer_size
}

// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-encodedbodysize
fn EncodedBodySize(&self) -> u64 {
self.encoded_body_size
}

// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-decodedbodysize
fn DecodedBodySize(&self) -> u64 {
self.decoded_body_size
}

// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-requeststart
fn RequestStart(&self) -> DOMHighResTimeStamp {
Finite::wrap(self.request_start)
@@ -16,15 +16,15 @@ interface PerformanceResourceTiming : PerformanceEntry {
readonly attribute DOMHighResTimeStamp redirectEnd;
readonly attribute DOMHighResTimeStamp fetchStart;
readonly attribute DOMHighResTimeStamp domainLookupStart;
// readonly attribute DOMHighResTimeStamp domainLookupEnd;
readonly attribute DOMHighResTimeStamp domainLookupEnd;
readonly attribute DOMHighResTimeStamp connectStart;
readonly attribute DOMHighResTimeStamp connectEnd;
// readonly attribute DOMHighResTimeStamp secureConnectionStart;
readonly attribute DOMHighResTimeStamp secureConnectionStart;
readonly attribute DOMHighResTimeStamp requestStart;
readonly attribute DOMHighResTimeStamp responseStart;
readonly attribute DOMHighResTimeStamp responseEnd;
/// readonly attribute unsigned long long transferSize;
/// readonly attribute unsigned long long encodedBodySize;
/// readonly attribute unsigned long long decodedBodySize;
readonly attribute unsigned long long transferSize;
readonly attribute unsigned long long encodedBodySize;
readonly attribute unsigned long long decodedBodySize;
[Default] object toJSON();
};
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.