mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Auto merge of #20459 - avadacatavra:time-origin, r=avadacatavra
Updating performance implementation and putting more measurements in <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [ ] `./mach build -d` does not report any errors - [ ] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20459) <!-- Reviewable:end -->
This commit is contained in:
commit
5da1069491
103 changed files with 1881 additions and 322 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2591,6 +2591,7 @@ dependencies = [
|
||||||
"servo_config 0.0.1",
|
"servo_config 0.0.1",
|
||||||
"servo_url 0.0.1",
|
"servo_url 0.0.1",
|
||||||
"std_test_override 0.0.1",
|
"std_test_override 0.0.1",
|
||||||
|
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"webrender_api 0.57.2 (git+https://github.com/servo/webrender)",
|
"webrender_api 0.57.2 (git+https://github.com/servo/webrender)",
|
||||||
|
|
|
@ -22,7 +22,7 @@ use mime_guess::guess_mime_type;
|
||||||
use net_traits::request::{CredentialsMode, Destination, Referrer, Request, RequestMode};
|
use net_traits::request::{CredentialsMode, Destination, Referrer, Request, RequestMode};
|
||||||
use net_traits::request::{Origin, ResponseTainting, Window};
|
use net_traits::request::{Origin, ResponseTainting, Window};
|
||||||
use net_traits::response::{Response, ResponseBody, ResponseType};
|
use net_traits::response::{Response, ResponseBody, ResponseType};
|
||||||
use net_traits::{FetchTaskTarget, NetworkError, ReferrerPolicy};
|
use net_traits::{FetchTaskTarget, NetworkError, ReferrerPolicy, ResourceFetchTiming};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -55,6 +55,7 @@ pub struct FetchContext {
|
||||||
pub devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
pub devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||||
pub filemanager: FileManager,
|
pub filemanager: FileManager,
|
||||||
pub cancellation_listener: Arc<Mutex<CancellationListener>>,
|
pub cancellation_listener: Arc<Mutex<CancellationListener>>,
|
||||||
|
pub timing: Arc<Mutex<ResourceFetchTiming>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CancellationListener {
|
pub struct CancellationListener {
|
||||||
|
@ -503,7 +504,7 @@ fn scheme_fetch(
|
||||||
|
|
||||||
match url.scheme() {
|
match url.scheme() {
|
||||||
"about" if url.path() == "blank" => {
|
"about" if url.path() == "blank" => {
|
||||||
let mut response = Response::new(url);
|
let mut response = Response::new(url, ResourceFetchTiming::new(request.timing_type()));
|
||||||
response
|
response
|
||||||
.headers
|
.headers
|
||||||
.typed_insert(ContentType::from(mime::TEXT_HTML_UTF_8));
|
.typed_insert(ContentType::from(mime::TEXT_HTML_UTF_8));
|
||||||
|
@ -517,7 +518,8 @@ fn scheme_fetch(
|
||||||
|
|
||||||
"data" => match decode(&url) {
|
"data" => match decode(&url) {
|
||||||
Ok((mime, bytes)) => {
|
Ok((mime, bytes)) => {
|
||||||
let mut response = Response::new(url);
|
let mut response =
|
||||||
|
Response::new(url, ResourceFetchTiming::new(request.timing_type()));
|
||||||
*response.body.lock().unwrap() = ResponseBody::Done(bytes);
|
*response.body.lock().unwrap() = ResponseBody::Done(bytes);
|
||||||
response.headers.typed_insert(ContentType::from(mime));
|
response.headers.typed_insert(ContentType::from(mime));
|
||||||
response
|
response
|
||||||
|
@ -537,7 +539,8 @@ fn scheme_fetch(
|
||||||
if let Ok(file) = File::open(file_path.clone()) {
|
if let Ok(file) = File::open(file_path.clone()) {
|
||||||
let mime = guess_mime_type(file_path);
|
let mime = guess_mime_type(file_path);
|
||||||
|
|
||||||
let mut response = Response::new(url);
|
let mut response =
|
||||||
|
Response::new(url, ResourceFetchTiming::new(request.timing_type()));
|
||||||
response.headers.typed_insert(ContentType::from(mime));
|
response.headers.typed_insert(ContentType::from(mime));
|
||||||
|
|
||||||
let (done_sender, done_receiver) = unbounded();
|
let (done_sender, done_receiver) = unbounded();
|
||||||
|
@ -656,7 +659,8 @@ fn scheme_fetch(
|
||||||
|
|
||||||
match load_blob_sync(url.clone(), context.filemanager.clone()) {
|
match load_blob_sync(url.clone(), context.filemanager.clone()) {
|
||||||
Ok((headers, bytes)) => {
|
Ok((headers, bytes)) => {
|
||||||
let mut response = Response::new(url);
|
let mut response =
|
||||||
|
Response::new(url, ResourceFetchTiming::new(request.timing_type()));
|
||||||
response.headers = headers;
|
response.headers = headers;
|
||||||
*response.body.lock().unwrap() = ResponseBody::Done(bytes);
|
*response.body.lock().unwrap() = ResponseBody::Done(bytes);
|
||||||
response
|
response
|
||||||
|
|
|
@ -20,7 +20,7 @@ use malloc_size_of::{
|
||||||
};
|
};
|
||||||
use net_traits::request::Request;
|
use net_traits::request::Request;
|
||||||
use net_traits::response::{HttpsState, Response, ResponseBody};
|
use net_traits::response::{HttpsState, Response, ResponseBody};
|
||||||
use net_traits::{FetchMetadata, Metadata};
|
use net_traits::{FetchMetadata, Metadata, ResourceFetchTiming};
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use servo_config::prefs::PREFS;
|
use servo_config::prefs::PREFS;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
|
@ -302,7 +302,11 @@ fn create_cached_response(
|
||||||
cached_headers: &HeaderMap,
|
cached_headers: &HeaderMap,
|
||||||
done_chan: &mut DoneChannel,
|
done_chan: &mut DoneChannel,
|
||||||
) -> CachedResponse {
|
) -> CachedResponse {
|
||||||
let mut response = Response::new(cached_resource.data.metadata.data.final_url.clone());
|
let resource_timing = ResourceFetchTiming::new(request.timing_type());
|
||||||
|
let mut response = Response::new(
|
||||||
|
cached_resource.data.metadata.data.final_url.clone(),
|
||||||
|
resource_timing,
|
||||||
|
);
|
||||||
response.headers = cached_headers.clone();
|
response.headers = cached_headers.clone();
|
||||||
response.body = cached_resource.body.clone();
|
response.body = cached_resource.body.clone();
|
||||||
if let ResponseBody::Receiving(_) = *cached_resource.body.lock().unwrap() {
|
if let ResponseBody::Receiving(_) = *cached_resource.body.lock().unwrap() {
|
||||||
|
@ -687,8 +691,11 @@ impl HttpCache {
|
||||||
// Received a response with 304 status code, in response to a request that matches a cached resource.
|
// Received a response with 304 status code, in response to a request that matches a cached resource.
|
||||||
// 1. update the headers of the cached resource.
|
// 1. update the headers of the cached resource.
|
||||||
// 2. return a response, constructed from the cached resource.
|
// 2. return a response, constructed from the cached resource.
|
||||||
let mut constructed_response =
|
let resource_timing = ResourceFetchTiming::new(request.timing_type());
|
||||||
Response::new(cached_resource.data.metadata.data.final_url.clone());
|
let mut constructed_response = Response::new(
|
||||||
|
cached_resource.data.metadata.data.final_url.clone(),
|
||||||
|
resource_timing,
|
||||||
|
);
|
||||||
constructed_response.body = cached_resource.body.clone();
|
constructed_response.body = cached_resource.body.clone();
|
||||||
constructed_response.status = cached_resource.data.status.clone();
|
constructed_response.status = cached_resource.data.status.clone();
|
||||||
constructed_response.https_state = cached_resource.data.https_state.clone();
|
constructed_response.https_state = cached_resource.data.https_state.clone();
|
||||||
|
|
|
@ -43,6 +43,7 @@ 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};
|
||||||
use net_traits::response::{HttpsState, Response, ResponseBody, ResponseType};
|
use net_traits::response::{HttpsState, Response, ResponseBody, ResponseType};
|
||||||
|
use net_traits::ResourceAttribute;
|
||||||
use net_traits::{CookieSource, FetchMetadata, NetworkError, ReferrerPolicy};
|
use net_traits::{CookieSource, FetchMetadata, NetworkError, ReferrerPolicy};
|
||||||
use openssl::ssl::SslConnectorBuilder;
|
use openssl::ssl::SslConnectorBuilder;
|
||||||
use servo_url::{ImmutableOrigin, ServoUrl};
|
use servo_url::{ImmutableOrigin, ServoUrl};
|
||||||
|
@ -408,14 +409,8 @@ fn obtain_response(
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if log_enabled!(log::Level::Info) {
|
// TODO(#21261) connect_start: set if a persistent connection is *not* used and the last non-redirected
|
||||||
info!("{} {}", method, url);
|
// fetch passes the timing allow check
|
||||||
for header in headers.iter() {
|
|
||||||
info!(" - {:?}", header);
|
|
||||||
}
|
|
||||||
info!("{:?}", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
let connect_start = precise_time_ms();
|
let connect_start = precise_time_ms();
|
||||||
// https://url.spec.whatwg.org/#percent-encoded-bytes
|
// https://url.spec.whatwg.org/#percent-encoded-bytes
|
||||||
let request = HyperRequest::builder()
|
let request = HyperRequest::builder()
|
||||||
|
@ -435,6 +430,8 @@ fn obtain_response(
|
||||||
Err(e) => return Box::new(future::result(Err(NetworkError::from_http_error(&e)))),
|
Err(e) => return Box::new(future::result(Err(NetworkError::from_http_error(&e)))),
|
||||||
};
|
};
|
||||||
*request.headers_mut() = headers.clone();
|
*request.headers_mut() = headers.clone();
|
||||||
|
|
||||||
|
//TODO(#21262) connect_end
|
||||||
let connect_end = precise_time_ms();
|
let connect_end = precise_time_ms();
|
||||||
|
|
||||||
let request_id = request_id.map(|v| v.to_owned());
|
let request_id = request_id.map(|v| v.to_owned());
|
||||||
|
@ -449,6 +446,8 @@ fn obtain_response(
|
||||||
.and_then(move |res| {
|
.and_then(move |res| {
|
||||||
let send_end = precise_time_ms();
|
let send_end = precise_time_ms();
|
||||||
|
|
||||||
|
// TODO(#21271) response_start: immediately after receiving first byte of response
|
||||||
|
|
||||||
let msg = if let Some(request_id) = request_id {
|
let msg = if let Some(request_id) = request_id {
|
||||||
if let Some(pipeline_id) = pipeline_id {
|
if let Some(pipeline_id) = pipeline_id {
|
||||||
Some(prepare_devtools_request(
|
Some(prepare_devtools_request(
|
||||||
|
@ -483,6 +482,7 @@ fn obtain_response(
|
||||||
})
|
})
|
||||||
.map_err(move |e| NetworkError::from_hyper_error(&e)),
|
.map_err(move |e| NetworkError::from_hyper_error(&e)),
|
||||||
)
|
)
|
||||||
|
// TODO(#21263) response_end (also needs to be set above if fetch is aborted due to an error)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [HTTP fetch](https://fetch.spec.whatwg.org#http-fetch)
|
/// [HTTP fetch](https://fetch.spec.whatwg.org#http-fetch)
|
||||||
|
@ -571,6 +571,19 @@ pub fn http_fetch(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Substep 3
|
// Substep 3
|
||||||
|
// TODO(#21258) maybe set fetch_start (if this is the last resource)
|
||||||
|
// 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(#21256) maybe set redirect_start if this resource initiates the redirect
|
||||||
|
// TODO(#21254) also set startTime equal to either fetch_start or redirect_start
|
||||||
|
// (https://w3c.github.io/resource-timing/#dfn-starttime)
|
||||||
|
context
|
||||||
|
.timing
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.set_attribute(ResourceAttribute::RequestStart);
|
||||||
|
|
||||||
let mut fetch_result = http_network_or_cache_fetch(
|
let mut fetch_result = http_network_or_cache_fetch(
|
||||||
request,
|
request,
|
||||||
authentication_fetch_flag,
|
authentication_fetch_flag,
|
||||||
|
@ -640,8 +653,22 @@ pub fn http_fetch(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO redirect_end: last byte of response of last redirect
|
||||||
|
|
||||||
// set back to default
|
// set back to default
|
||||||
response.return_internal = true;
|
response.return_internal = true;
|
||||||
|
context
|
||||||
|
.timing
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.set_attribute(ResourceAttribute::RedirectCount(
|
||||||
|
request.redirect_count as u16,
|
||||||
|
));
|
||||||
|
|
||||||
|
let timing = &*context.timing.lock().unwrap();
|
||||||
|
response.resource_timing = timing.clone();
|
||||||
|
|
||||||
// Step 6
|
// Step 6
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
@ -1199,7 +1226,8 @@ fn http_network_fetch(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut response = Response::new(url.clone());
|
let timing = &*context.timing.lock().unwrap();
|
||||||
|
let mut response = Response::new(url.clone(), timing.clone());
|
||||||
response.status = Some((
|
response.status = Some((
|
||||||
res.status(),
|
res.status(),
|
||||||
res.status().canonical_reason().unwrap_or("").into(),
|
res.status().canonical_reason().unwrap_or("").into(),
|
||||||
|
@ -1224,6 +1252,7 @@ fn http_network_fetch(
|
||||||
FetchMetadata::Unfiltered(m) => m,
|
FetchMetadata::Unfiltered(m) => m,
|
||||||
FetchMetadata::Filtered { unsafe_, .. } => unsafe_,
|
FetchMetadata::Filtered { unsafe_, .. } => unsafe_,
|
||||||
};
|
};
|
||||||
|
|
||||||
let devtools_sender = context.devtools_chan.clone();
|
let devtools_sender = context.devtools_chan.clone();
|
||||||
let meta_status = meta.status.clone();
|
let meta_status = meta.status.clone();
|
||||||
let meta_headers = meta.headers.clone();
|
let meta_headers = meta.headers.clone();
|
||||||
|
|
|
@ -503,11 +503,11 @@ impl ImageCache for ImageCacheImpl {
|
||||||
(FetchResponseMsg::ProcessResponseEOF(result), key) => {
|
(FetchResponseMsg::ProcessResponseEOF(result), key) => {
|
||||||
debug!("Received EOF for {:?}", key);
|
debug!("Received EOF for {:?}", key);
|
||||||
match result {
|
match result {
|
||||||
Ok(()) => {
|
Ok(_) => {
|
||||||
let bytes = {
|
let bytes = {
|
||||||
let mut store = self.store.lock().unwrap();
|
let mut store = self.store.lock().unwrap();
|
||||||
let pending_load = store.pending_loads.get_by_key_mut(&id).unwrap();
|
let pending_load = store.pending_loads.get_by_key_mut(&id).unwrap();
|
||||||
pending_load.result = Some(result);
|
pending_load.result = Some(Ok(()));
|
||||||
debug!("Async decoding {} ({:?})", pending_load.url, key);
|
debug!("Async decoding {} ({:?})", pending_load.url, key);
|
||||||
pending_load.bytes.mark_complete()
|
pending_load.bytes.mark_complete()
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,13 +22,14 @@ use embedder_traits::EmbedderProxy;
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
use ipc_channel::ipc::{self, IpcReceiver, IpcReceiverSet, IpcSender};
|
use ipc_channel::ipc::{self, IpcReceiver, IpcReceiverSet, IpcSender};
|
||||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||||
use net_traits::request::{Request, RequestInit};
|
use net_traits::request::{Destination, Request, RequestInit};
|
||||||
use net_traits::response::{Response, ResponseInit};
|
use net_traits::response::{Response, ResponseInit};
|
||||||
use net_traits::storage_thread::StorageThreadMsg;
|
use net_traits::storage_thread::StorageThreadMsg;
|
||||||
use net_traits::WebSocketNetworkEvent;
|
use net_traits::WebSocketNetworkEvent;
|
||||||
use net_traits::{CookieSource, CoreResourceThread};
|
use net_traits::{CookieSource, CoreResourceMsg, CoreResourceThread};
|
||||||
use net_traits::{CoreResourceMsg, CustomResponseMediator, FetchChannels};
|
use net_traits::{CustomResponseMediator, FetchChannels};
|
||||||
use net_traits::{FetchResponseMsg, ResourceThreads, WebSocketDomAction};
|
use net_traits::{FetchResponseMsg, ResourceThreads, WebSocketDomAction};
|
||||||
|
use net_traits::{ResourceFetchTiming, ResourceTimingType};
|
||||||
use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
||||||
use profile_traits::mem::{Report, ReportKind, ReportsChan};
|
use profile_traits::mem::{Report, ReportKind, ReportsChan};
|
||||||
use profile_traits::time::ProfilerChan;
|
use profile_traits::time::ProfilerChan;
|
||||||
|
@ -440,6 +441,11 @@ impl CoreResourceManager {
|
||||||
let dc = self.devtools_chan.clone();
|
let dc = self.devtools_chan.clone();
|
||||||
let filemanager = self.filemanager.clone();
|
let filemanager = self.filemanager.clone();
|
||||||
|
|
||||||
|
let timing_type = match req_init.destination {
|
||||||
|
Destination::Document => ResourceTimingType::Navigation,
|
||||||
|
_ => ResourceTimingType::Resource,
|
||||||
|
};
|
||||||
|
|
||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
.name(format!("fetch thread for {}", req_init.url))
|
.name(format!("fetch thread for {}", req_init.url))
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
|
@ -456,11 +462,12 @@ impl CoreResourceManager {
|
||||||
cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(
|
cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(
|
||||||
cancel_chan,
|
cancel_chan,
|
||||||
))),
|
))),
|
||||||
|
timing: Arc::new(Mutex::new(ResourceFetchTiming::new(request.timing_type()))),
|
||||||
};
|
};
|
||||||
|
|
||||||
match res_init_ {
|
match res_init_ {
|
||||||
Some(res_init) => {
|
Some(res_init) => {
|
||||||
let response = Response::from_init(res_init);
|
let response = Response::from_init(res_init, timing_type);
|
||||||
http_redirect_fetch(
|
http_redirect_fetch(
|
||||||
&mut request,
|
&mut request,
|
||||||
&mut CorsCache::new(),
|
&mut CorsCache::new(),
|
||||||
|
|
|
@ -35,9 +35,9 @@ use net::hsts::HstsEntry;
|
||||||
use net::test::HttpState;
|
use net::test::HttpState;
|
||||||
use net_traits::request::{Destination, Origin, RedirectMode, Referrer, Request, RequestMode};
|
use net_traits::request::{Destination, Origin, RedirectMode, Referrer, Request, RequestMode};
|
||||||
use net_traits::response::{CacheState, Response, ResponseBody, ResponseType};
|
use net_traits::response::{CacheState, Response, ResponseBody, ResponseType};
|
||||||
use net_traits::IncludeSubdomains;
|
use net_traits::{
|
||||||
use net_traits::NetworkError;
|
IncludeSubdomains, NetworkError, ReferrerPolicy, ResourceFetchTiming, ResourceTimingType,
|
||||||
use net_traits::ReferrerPolicy;
|
};
|
||||||
use servo_url::{ImmutableOrigin, ServoUrl};
|
use servo_url::{ImmutableOrigin, ServoUrl};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
@ -127,7 +127,7 @@ fn test_fetch_blob() {
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use net_traits::blob_url_store::BlobBuf;
|
use net_traits::blob_url_store::BlobBuf;
|
||||||
|
|
||||||
let context = new_fetch_context(None, None);
|
let mut context = new_fetch_context(None, None);
|
||||||
|
|
||||||
let bytes = b"content";
|
let bytes = b"content";
|
||||||
let blob_buf = BlobBuf {
|
let blob_buf = BlobBuf {
|
||||||
|
@ -147,7 +147,7 @@ fn test_fetch_blob() {
|
||||||
let url = ServoUrl::parse(&format!("blob:{}{}", origin.as_str(), id.to_simple())).unwrap();
|
let url = ServoUrl::parse(&format!("blob:{}{}", origin.as_str(), id.to_simple())).unwrap();
|
||||||
|
|
||||||
let mut request = Request::new(url, Some(Origin::Origin(origin.origin())), None);
|
let mut request = Request::new(url, Some(Origin::Origin(origin.origin())), None);
|
||||||
let fetch_response = fetch_with_context(&mut request, &context);
|
let fetch_response = fetch_with_context(&mut request, &mut context);
|
||||||
|
|
||||||
assert!(!fetch_response.is_network_error());
|
assert!(!fetch_response.is_network_error());
|
||||||
|
|
||||||
|
@ -649,12 +649,15 @@ fn test_fetch_with_hsts() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let ssl_client = create_ssl_connector_builder(&ca_content);
|
let ssl_client = create_ssl_connector_builder(&ca_content);
|
||||||
|
|
||||||
let context = FetchContext {
|
let mut context = FetchContext {
|
||||||
state: Arc::new(HttpState::new(ssl_client)),
|
state: Arc::new(HttpState::new(ssl_client)),
|
||||||
user_agent: DEFAULT_USER_AGENT.into(),
|
user_agent: DEFAULT_USER_AGENT.into(),
|
||||||
devtools_chan: None,
|
devtools_chan: None,
|
||||||
filemanager: FileManager::new(create_embedder_proxy()),
|
filemanager: FileManager::new(create_embedder_proxy()),
|
||||||
cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(None))),
|
cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(None))),
|
||||||
|
timing: Arc::new(Mutex::new(ResourceFetchTiming::new(
|
||||||
|
ResourceTimingType::Navigation,
|
||||||
|
))),
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -668,7 +671,7 @@ fn test_fetch_with_hsts() {
|
||||||
request.referrer = Referrer::NoReferrer;
|
request.referrer = Referrer::NoReferrer;
|
||||||
// Set the flag.
|
// Set the flag.
|
||||||
request.local_urls_only = false;
|
request.local_urls_only = false;
|
||||||
let response = fetch_with_context(&mut request, &context);
|
let response = fetch_with_context(&mut request, &mut context);
|
||||||
server.close();
|
server.close();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
response.internal_response.unwrap().url().unwrap().scheme(),
|
response.internal_response.unwrap().url().unwrap().scheme(),
|
||||||
|
|
|
@ -587,8 +587,8 @@ fn test_load_doesnt_add_host_to_sts_list_when_url_is_http_even_if_sts_headers_ar
|
||||||
pipeline_id: Some(TEST_PIPELINE_ID),
|
pipeline_id: Some(TEST_PIPELINE_ID),
|
||||||
..RequestInit::default()
|
..RequestInit::default()
|
||||||
});
|
});
|
||||||
let context = new_fetch_context(None, None);
|
let mut context = new_fetch_context(None, None);
|
||||||
let response = fetch_with_context(&mut request, &context);
|
let response = fetch_with_context(&mut request, &mut context);
|
||||||
|
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
|
@ -623,7 +623,7 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_
|
||||||
};
|
};
|
||||||
let (server, url) = make_server(handler);
|
let (server, url) = make_server(handler);
|
||||||
|
|
||||||
let context = new_fetch_context(None, None);
|
let mut context = new_fetch_context(None, None);
|
||||||
|
|
||||||
assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None);
|
assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None);
|
||||||
|
|
||||||
|
@ -637,7 +637,7 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_
|
||||||
credentials_mode: CredentialsMode::Include,
|
credentials_mode: CredentialsMode::Include,
|
||||||
..RequestInit::default()
|
..RequestInit::default()
|
||||||
});
|
});
|
||||||
let response = fetch_with_context(&mut request, &context);
|
let response = fetch_with_context(&mut request, &mut context);
|
||||||
|
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
|
@ -669,7 +669,7 @@ fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_re
|
||||||
};
|
};
|
||||||
let (server, url) = make_server(handler);
|
let (server, url) = make_server(handler);
|
||||||
|
|
||||||
let context = new_fetch_context(None, None);
|
let mut context = new_fetch_context(None, None);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut cookie_jar = context.state.cookie_jar.write().unwrap();
|
let mut cookie_jar = context.state.cookie_jar.write().unwrap();
|
||||||
|
@ -692,7 +692,7 @@ fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_re
|
||||||
credentials_mode: CredentialsMode::Include,
|
credentials_mode: CredentialsMode::Include,
|
||||||
..RequestInit::default()
|
..RequestInit::default()
|
||||||
});
|
});
|
||||||
let response = fetch_with_context(&mut request, &context);
|
let response = fetch_with_context(&mut request, &mut context);
|
||||||
|
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
|
@ -718,7 +718,7 @@ fn test_load_sends_cookie_if_nonhttp() {
|
||||||
};
|
};
|
||||||
let (server, url) = make_server(handler);
|
let (server, url) = make_server(handler);
|
||||||
|
|
||||||
let context = new_fetch_context(None, None);
|
let mut context = new_fetch_context(None, None);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut cookie_jar = context.state.cookie_jar.write().unwrap();
|
let mut cookie_jar = context.state.cookie_jar.write().unwrap();
|
||||||
|
@ -741,7 +741,7 @@ fn test_load_sends_cookie_if_nonhttp() {
|
||||||
credentials_mode: CredentialsMode::Include,
|
credentials_mode: CredentialsMode::Include,
|
||||||
..RequestInit::default()
|
..RequestInit::default()
|
||||||
});
|
});
|
||||||
let response = fetch_with_context(&mut request, &context);
|
let response = fetch_with_context(&mut request, &mut context);
|
||||||
|
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
|
@ -767,7 +767,7 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl(
|
||||||
};
|
};
|
||||||
let (server, url) = make_server(handler);
|
let (server, url) = make_server(handler);
|
||||||
|
|
||||||
let context = new_fetch_context(None, None);
|
let mut context = new_fetch_context(None, None);
|
||||||
|
|
||||||
assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None);
|
assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None);
|
||||||
|
|
||||||
|
@ -781,7 +781,7 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl(
|
||||||
credentials_mode: CredentialsMode::Include,
|
credentials_mode: CredentialsMode::Include,
|
||||||
..RequestInit::default()
|
..RequestInit::default()
|
||||||
});
|
});
|
||||||
let response = fetch_with_context(&mut request, &context);
|
let response = fetch_with_context(&mut request, &mut context);
|
||||||
|
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
|
@ -819,7 +819,7 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() {
|
||||||
};
|
};
|
||||||
let (server, url) = make_server(handler);
|
let (server, url) = make_server(handler);
|
||||||
|
|
||||||
let context = new_fetch_context(None, None);
|
let mut context = new_fetch_context(None, None);
|
||||||
|
|
||||||
assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None);
|
assert_cookie_for_domain(&context.state.cookie_jar, url.as_str(), None);
|
||||||
|
|
||||||
|
@ -833,7 +833,7 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() {
|
||||||
credentials_mode: CredentialsMode::Include,
|
credentials_mode: CredentialsMode::Include,
|
||||||
..RequestInit::default()
|
..RequestInit::default()
|
||||||
});
|
});
|
||||||
let response = fetch_with_context(&mut request, &context);
|
let response = fetch_with_context(&mut request, &mut context);
|
||||||
|
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
|
@ -1242,7 +1242,7 @@ fn test_redirect_from_x_to_y_provides_y_cookies_from_y() {
|
||||||
let url_y = ServoUrl::parse(&format!("http://mozilla.org:{}/org/", port)).unwrap();
|
let url_y = ServoUrl::parse(&format!("http://mozilla.org:{}/org/", port)).unwrap();
|
||||||
*shared_url_y_clone.lock().unwrap() = Some(url_y.clone());
|
*shared_url_y_clone.lock().unwrap() = Some(url_y.clone());
|
||||||
|
|
||||||
let context = new_fetch_context(None, None);
|
let mut context = new_fetch_context(None, None);
|
||||||
{
|
{
|
||||||
let mut cookie_jar = context.state.cookie_jar.write().unwrap();
|
let mut cookie_jar = context.state.cookie_jar.write().unwrap();
|
||||||
let cookie_x = Cookie::new_wrapped(
|
let cookie_x = Cookie::new_wrapped(
|
||||||
|
@ -1272,7 +1272,7 @@ fn test_redirect_from_x_to_y_provides_y_cookies_from_y() {
|
||||||
credentials_mode: CredentialsMode::Include,
|
credentials_mode: CredentialsMode::Include,
|
||||||
..RequestInit::default()
|
..RequestInit::default()
|
||||||
});
|
});
|
||||||
let response = fetch_with_context(&mut request, &context);
|
let response = fetch_with_context(&mut request, &mut context);
|
||||||
|
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
|
@ -1355,7 +1355,7 @@ fn test_if_auth_creds_not_in_url_but_in_cache_it_sets_it() {
|
||||||
credentials_mode: CredentialsMode::Include,
|
credentials_mode: CredentialsMode::Include,
|
||||||
..RequestInit::default()
|
..RequestInit::default()
|
||||||
});
|
});
|
||||||
let context = new_fetch_context(None, None);
|
let mut context = new_fetch_context(None, None);
|
||||||
|
|
||||||
let auth_entry = AuthCacheEntry {
|
let auth_entry = AuthCacheEntry {
|
||||||
user_name: "username".to_owned(),
|
user_name: "username".to_owned(),
|
||||||
|
@ -1370,7 +1370,7 @@ fn test_if_auth_creds_not_in_url_but_in_cache_it_sets_it() {
|
||||||
.entries
|
.entries
|
||||||
.insert(url.origin().clone().ascii_serialization(), auth_entry);
|
.insert(url.origin().clone().ascii_serialization(), auth_entry);
|
||||||
|
|
||||||
let response = fetch_with_context(&mut request, &context);
|
let response = fetch_with_context(&mut request, &mut context);
|
||||||
|
|
||||||
let _ = server.close();
|
let _ = server.close();
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ use net::filemanager_thread::FileManager;
|
||||||
use net::test::HttpState;
|
use net::test::HttpState;
|
||||||
use net_traits::request::Request;
|
use net_traits::request::Request;
|
||||||
use net_traits::response::Response;
|
use net_traits::response::Response;
|
||||||
use net_traits::FetchTaskTarget;
|
use net_traits::{FetchTaskTarget, ResourceFetchTiming, ResourceTimingType};
|
||||||
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
|
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::net::TcpListener as StdTcpListener;
|
use std::net::TcpListener as StdTcpListener;
|
||||||
|
@ -93,6 +93,9 @@ fn new_fetch_context(
|
||||||
devtools_chan: dc,
|
devtools_chan: dc,
|
||||||
filemanager: FileManager::new(sender),
|
filemanager: FileManager::new(sender),
|
||||||
cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(None))),
|
cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(None))),
|
||||||
|
timing: Arc::new(Mutex::new(ResourceFetchTiming::new(
|
||||||
|
ResourceTimingType::Navigation,
|
||||||
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl FetchTaskTarget for FetchResponseCollector {
|
impl FetchTaskTarget for FetchResponseCollector {
|
||||||
|
@ -107,14 +110,14 @@ impl FetchTaskTarget for FetchResponseCollector {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch(request: &mut Request, dc: Option<Sender<DevtoolsControlMsg>>) -> Response {
|
fn fetch(request: &mut Request, dc: Option<Sender<DevtoolsControlMsg>>) -> Response {
|
||||||
fetch_with_context(request, &new_fetch_context(dc, None))
|
fetch_with_context(request, &mut new_fetch_context(dc, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_with_context(request: &mut Request, context: &FetchContext) -> Response {
|
fn fetch_with_context(request: &mut Request, mut context: &mut FetchContext) -> Response {
|
||||||
let (sender, receiver) = unbounded();
|
let (sender, receiver) = unbounded();
|
||||||
let mut target = FetchResponseCollector { sender: sender };
|
let mut target = FetchResponseCollector { sender: sender };
|
||||||
|
|
||||||
methods::fetch(request, &mut target, context);
|
methods::fetch(request, &mut target, &mut context);
|
||||||
|
|
||||||
receiver.recv().unwrap()
|
receiver.recv().unwrap()
|
||||||
}
|
}
|
||||||
|
@ -123,7 +126,12 @@ fn fetch_with_cors_cache(request: &mut Request, cache: &mut CorsCache) -> Respon
|
||||||
let (sender, receiver) = unbounded();
|
let (sender, receiver) = unbounded();
|
||||||
let mut target = FetchResponseCollector { sender: sender };
|
let mut target = FetchResponseCollector { sender: sender };
|
||||||
|
|
||||||
methods::fetch_with_cors_cache(request, cache, &mut target, &new_fetch_context(None, None));
|
methods::fetch_with_cors_cache(
|
||||||
|
request,
|
||||||
|
cache,
|
||||||
|
&mut target,
|
||||||
|
&mut new_fetch_context(None, None),
|
||||||
|
);
|
||||||
|
|
||||||
receiver.recv().unwrap()
|
receiver.recv().unwrap()
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
use net::subresource_integrity::{get_prioritized_hash_function, get_strongest_metadata, SriEntry};
|
use net::subresource_integrity::{get_prioritized_hash_function, get_strongest_metadata, SriEntry};
|
||||||
use net::subresource_integrity::{is_response_integrity_valid, parsed_metadata};
|
use net::subresource_integrity::{is_response_integrity_valid, parsed_metadata};
|
||||||
use net_traits::response::{Response, ResponseBody};
|
use net_traits::response::{Response, ResponseBody};
|
||||||
|
use net_traits::{ResourceFetchTiming, ResourceTimingType};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -70,7 +71,10 @@ fn test_get_strongest_metadata_different_algorithm() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_response_integrity_valid() {
|
fn test_response_integrity_valid() {
|
||||||
let url: ServoUrl = ServoUrl::parse("http://servo.org").unwrap();
|
let url: ServoUrl = ServoUrl::parse("http://servo.org").unwrap();
|
||||||
let response: Response = Response::new(url);
|
let response: Response = Response::new(
|
||||||
|
url,
|
||||||
|
ResourceFetchTiming::new(ResourceTimingType::Navigation),
|
||||||
|
);
|
||||||
|
|
||||||
let integrity_metadata =
|
let integrity_metadata =
|
||||||
"sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO";
|
"sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO";
|
||||||
|
@ -83,7 +87,10 @@ fn test_response_integrity_valid() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_response_integrity_invalid() {
|
fn test_response_integrity_invalid() {
|
||||||
let url: ServoUrl = ServoUrl::parse("http://servo.org").unwrap();
|
let url: ServoUrl = ServoUrl::parse("http://servo.org").unwrap();
|
||||||
let response: Response = Response::new(url);
|
let response: Response = Response::new(
|
||||||
|
url,
|
||||||
|
ResourceFetchTiming::new(ResourceTimingType::Navigation),
|
||||||
|
);
|
||||||
|
|
||||||
let integrity_metadata =
|
let integrity_metadata =
|
||||||
"sha256-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO";
|
"sha256-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO";
|
||||||
|
|
|
@ -36,6 +36,7 @@ serde = "1.0"
|
||||||
servo_arc = {path = "../servo_arc"}
|
servo_arc = {path = "../servo_arc"}
|
||||||
servo_config = {path = "../config"}
|
servo_config = {path = "../config"}
|
||||||
servo_url = {path = "../url"}
|
servo_url = {path = "../url"}
|
||||||
|
time = "0.1"
|
||||||
url = "1.2"
|
url = "1.2"
|
||||||
uuid = {version = "0.7", features = ["v4", "serde"]}
|
uuid = {version = "0.7", features = ["v4", "serde"]}
|
||||||
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
|
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
|
||||||
|
|
|
@ -35,6 +35,7 @@ use mime::Mime;
|
||||||
use msg::constellation_msg::HistoryStateId;
|
use msg::constellation_msg::HistoryStateId;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use time::precise_time_ns;
|
||||||
use url::percent_encoding;
|
use url::percent_encoding;
|
||||||
|
|
||||||
pub mod blob_url_store;
|
pub mod blob_url_store;
|
||||||
|
@ -157,7 +158,7 @@ pub enum FetchResponseMsg {
|
||||||
// todo: send more info about the response (or perhaps the entire Response)
|
// todo: send more info about the response (or perhaps the entire Response)
|
||||||
ProcessResponse(Result<FetchMetadata, NetworkError>),
|
ProcessResponse(Result<FetchMetadata, NetworkError>),
|
||||||
ProcessResponseChunk(Vec<u8>),
|
ProcessResponseChunk(Vec<u8>),
|
||||||
ProcessResponseEOF(Result<(), NetworkError>),
|
ProcessResponseEOF(Result<ResourceFetchTiming, NetworkError>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FetchTaskTarget {
|
pub trait FetchTaskTarget {
|
||||||
|
@ -207,7 +208,10 @@ pub trait FetchResponseListener {
|
||||||
fn process_request_eof(&mut self);
|
fn process_request_eof(&mut self);
|
||||||
fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>);
|
fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>);
|
||||||
fn process_response_chunk(&mut self, chunk: Vec<u8>);
|
fn process_response_chunk(&mut self, chunk: Vec<u8>);
|
||||||
fn process_response_eof(&mut self, response: Result<(), NetworkError>);
|
fn process_response_eof(&mut self, response: Result<ResourceFetchTiming, NetworkError>);
|
||||||
|
fn resource_timing(&self) -> &ResourceFetchTiming;
|
||||||
|
fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming;
|
||||||
|
fn submit_resource_timing(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FetchTaskTarget for IpcSender<FetchResponseMsg> {
|
impl FetchTaskTarget for IpcSender<FetchResponseMsg> {
|
||||||
|
@ -231,7 +235,9 @@ impl FetchTaskTarget for IpcSender<FetchResponseMsg> {
|
||||||
if let Some(e) = response.get_network_error() {
|
if let Some(e) = response.get_network_error() {
|
||||||
let _ = self.send(FetchResponseMsg::ProcessResponseEOF(Err(e.clone())));
|
let _ = self.send(FetchResponseMsg::ProcessResponseEOF(Err(e.clone())));
|
||||||
} else {
|
} else {
|
||||||
let _ = self.send(FetchResponseMsg::ProcessResponseEOF(Ok(())));
|
let _ = self.send(FetchResponseMsg::ProcessResponseEOF(Ok(response
|
||||||
|
.get_resource_timing()
|
||||||
|
.clone())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,7 +254,23 @@ impl<T: FetchResponseListener> Action<T> for FetchResponseMsg {
|
||||||
FetchResponseMsg::ProcessRequestEOF => listener.process_request_eof(),
|
FetchResponseMsg::ProcessRequestEOF => listener.process_request_eof(),
|
||||||
FetchResponseMsg::ProcessResponse(meta) => listener.process_response(meta),
|
FetchResponseMsg::ProcessResponse(meta) => listener.process_response(meta),
|
||||||
FetchResponseMsg::ProcessResponseChunk(data) => listener.process_response_chunk(data),
|
FetchResponseMsg::ProcessResponseChunk(data) => listener.process_response_chunk(data),
|
||||||
FetchResponseMsg::ProcessResponseEOF(data) => listener.process_response_eof(data),
|
FetchResponseMsg::ProcessResponseEOF(data) => {
|
||||||
|
match data {
|
||||||
|
Ok(ref response_resource_timing) => {
|
||||||
|
// update listener with values from response
|
||||||
|
*listener.resource_timing_mut() = response_resource_timing.clone();
|
||||||
|
listener.process_response_eof(Ok(response_resource_timing.clone()));
|
||||||
|
// TODO timing check https://w3c.github.io/resource-timing/#dfn-timing-allow-check
|
||||||
|
|
||||||
|
listener.submit_resource_timing();
|
||||||
|
},
|
||||||
|
// TODO Resources for which the fetch was initiated, but was later aborted
|
||||||
|
// (e.g. due to a network error) MAY be included as PerformanceResourceTiming
|
||||||
|
// objects in the Performance Timeline and MUST contain initialized attribute
|
||||||
|
// values for processed substeps of the processing model.
|
||||||
|
Err(e) => listener.process_response_eof(Err(e)),
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -418,6 +440,55 @@ pub struct ResourceCorsData {
|
||||||
pub origin: ServoUrl,
|
pub origin: ServoUrl,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
|
||||||
|
pub struct ResourceFetchTiming {
|
||||||
|
pub timing_type: ResourceTimingType,
|
||||||
|
/// Number of redirects until final resource (currently limited to 20)
|
||||||
|
pub redirect_count: u16,
|
||||||
|
pub request_start: u64,
|
||||||
|
pub response_start: u64,
|
||||||
|
// pub response_end: u64,
|
||||||
|
// pub redirect_start: u64,
|
||||||
|
// pub redirect_end: u64,
|
||||||
|
// pub connect_start: u64,
|
||||||
|
// pub connect_end: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ResourceAttribute {
|
||||||
|
RedirectCount(u16),
|
||||||
|
RequestStart,
|
||||||
|
ResponseStart,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
||||||
|
pub enum ResourceTimingType {
|
||||||
|
Resource,
|
||||||
|
Navigation,
|
||||||
|
Error,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceFetchTiming {
|
||||||
|
pub fn new(timing_type: ResourceTimingType) -> ResourceFetchTiming {
|
||||||
|
ResourceFetchTiming {
|
||||||
|
timing_type: timing_type,
|
||||||
|
redirect_count: 0,
|
||||||
|
request_start: 0,
|
||||||
|
response_start: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
match attribute {
|
||||||
|
ResourceAttribute::RedirectCount(count) => self.redirect_count = count,
|
||||||
|
ResourceAttribute::RequestStart => self.request_start = precise_time_ns(),
|
||||||
|
ResourceAttribute::ResponseStart => self.response_start = precise_time_ns(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Metadata about a loaded resource, such as is obtained from HTTP headers.
|
/// Metadata about a loaded resource, such as is obtained from HTTP headers.
|
||||||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
|
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
|
||||||
pub struct Metadata {
|
pub struct Metadata {
|
||||||
|
@ -449,6 +520,8 @@ pub struct Metadata {
|
||||||
|
|
||||||
/// Referrer Policy of the Request used to obtain Response
|
/// Referrer Policy of the Request used to obtain Response
|
||||||
pub referrer_policy: Option<ReferrerPolicy>,
|
pub referrer_policy: Option<ReferrerPolicy>,
|
||||||
|
/// Performance information for navigation events
|
||||||
|
pub timing: Option<ResourceFetchTiming>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Metadata {
|
impl Metadata {
|
||||||
|
@ -465,6 +538,7 @@ impl Metadata {
|
||||||
https_state: HttpsState::None,
|
https_state: HttpsState::None,
|
||||||
referrer: None,
|
referrer: None,
|
||||||
referrer_policy: None,
|
referrer_policy: None,
|
||||||
|
timing: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,7 +597,7 @@ pub fn load_whole_resource(
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
FetchResponseMsg::ProcessResponseChunk(data) => buf.extend_from_slice(&data),
|
FetchResponseMsg::ProcessResponseChunk(data) => buf.extend_from_slice(&data),
|
||||||
FetchResponseMsg::ProcessResponseEOF(Ok(())) => return Ok((metadata.unwrap(), buf)),
|
FetchResponseMsg::ProcessResponseEOF(Ok(_)) => return Ok((metadata.unwrap(), buf)),
|
||||||
FetchResponseMsg::ProcessResponse(Err(e)) |
|
FetchResponseMsg::ProcessResponse(Err(e)) |
|
||||||
FetchResponseMsg::ProcessResponseEOF(Err(e)) => return Err(e),
|
FetchResponseMsg::ProcessResponseEOF(Err(e)) => return Err(e),
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use crate::ReferrerPolicy;
|
use crate::ReferrerPolicy;
|
||||||
|
use crate::ResourceTimingType;
|
||||||
use http::HeaderMap;
|
use http::HeaderMap;
|
||||||
use hyper::Method;
|
use hyper::Method;
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::PipelineId;
|
||||||
|
@ -365,6 +366,14 @@ impl Request {
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn timing_type(&self) -> ResourceTimingType {
|
||||||
|
if self.is_navigation_request() {
|
||||||
|
ResourceTimingType::Navigation
|
||||||
|
} else {
|
||||||
|
ResourceTimingType::Resource
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Referrer {
|
impl Referrer {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
//! The [Response](https://fetch.spec.whatwg.org/#responses) object
|
//! The [Response](https://fetch.spec.whatwg.org/#responses) object
|
||||||
//! resulting from a [fetch operation](https://fetch.spec.whatwg.org/#concept-fetch)
|
//! resulting from a [fetch operation](https://fetch.spec.whatwg.org/#concept-fetch)
|
||||||
use crate::{FetchMetadata, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy};
|
use crate::{FetchMetadata, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy};
|
||||||
|
use crate::{ResourceFetchTiming, ResourceTimingType};
|
||||||
use headers_core::HeaderMapExt;
|
use headers_core::HeaderMapExt;
|
||||||
use headers_ext::{AccessControlExposeHeaders, ContentType};
|
use headers_ext::{AccessControlExposeHeaders, ContentType};
|
||||||
use http::{HeaderMap, StatusCode};
|
use http::{HeaderMap, StatusCode};
|
||||||
|
@ -119,10 +120,12 @@ pub struct Response {
|
||||||
/// https://fetch.spec.whatwg.org/#concept-response-aborted
|
/// https://fetch.spec.whatwg.org/#concept-response-aborted
|
||||||
#[ignore_malloc_size_of = "AtomicBool heap size undefined"]
|
#[ignore_malloc_size_of = "AtomicBool heap size undefined"]
|
||||||
pub aborted: Arc<AtomicBool>,
|
pub aborted: Arc<AtomicBool>,
|
||||||
|
/// track network metrics
|
||||||
|
pub resource_timing: ResourceFetchTiming,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Response {
|
impl Response {
|
||||||
pub fn new(url: ServoUrl) -> Response {
|
pub fn new(url: ServoUrl, resource_timing: ResourceFetchTiming) -> Response {
|
||||||
Response {
|
Response {
|
||||||
response_type: ResponseType::Default,
|
response_type: ResponseType::Default,
|
||||||
termination_reason: None,
|
termination_reason: None,
|
||||||
|
@ -141,11 +144,12 @@ impl Response {
|
||||||
internal_response: None,
|
internal_response: None,
|
||||||
return_internal: true,
|
return_internal: true,
|
||||||
aborted: Arc::new(AtomicBool::new(false)),
|
aborted: Arc::new(AtomicBool::new(false)),
|
||||||
|
resource_timing: resource_timing,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_init(init: ResponseInit) -> Response {
|
pub fn from_init(init: ResponseInit, resource_timing_type: ResourceTimingType) -> Response {
|
||||||
let mut res = Response::new(init.url);
|
let mut res = Response::new(init.url, ResourceFetchTiming::new(resource_timing_type));
|
||||||
res.location_url = init.location_url;
|
res.location_url = init.location_url;
|
||||||
res.headers = init.headers;
|
res.headers = init.headers;
|
||||||
res.referrer = init.referrer;
|
res.referrer = init.referrer;
|
||||||
|
@ -174,6 +178,7 @@ impl Response {
|
||||||
internal_response: None,
|
internal_response: None,
|
||||||
return_internal: true,
|
return_internal: true,
|
||||||
aborted: Arc::new(AtomicBool::new(false)),
|
aborted: Arc::new(AtomicBool::new(false)),
|
||||||
|
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,6 +224,10 @@ impl Response {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_resource_timing(&self) -> &ResourceFetchTiming {
|
||||||
|
&self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert to a filtered response, of type `filter_type`.
|
/// Convert to a filtered response, of type `filter_type`.
|
||||||
/// Do not use with type Error or Default
|
/// Do not use with type Error or Default
|
||||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||||
|
|
|
@ -80,7 +80,7 @@ use net_traits::request::{Request, RequestInit};
|
||||||
use net_traits::response::HttpsState;
|
use net_traits::response::HttpsState;
|
||||||
use net_traits::response::{Response, ResponseBody};
|
use net_traits::response::{Response, ResponseBody};
|
||||||
use net_traits::storage_thread::StorageType;
|
use net_traits::storage_thread::StorageType;
|
||||||
use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceThreads};
|
use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceFetchTiming, ResourceThreads};
|
||||||
use offscreen_gl_context::GLLimits;
|
use offscreen_gl_context::GLLimits;
|
||||||
use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
use profile_traits::mem::ProfilerChan as MemProfilerChan;
|
||||||
use profile_traits::time::ProfilerChan as TimeProfilerChan;
|
use profile_traits::time::ProfilerChan as TimeProfilerChan;
|
||||||
|
@ -466,6 +466,7 @@ unsafe_no_jsmanaged_fields!(AnalysisEngine, DistanceModel, PanningModel, ParamTy
|
||||||
unsafe_no_jsmanaged_fields!(dyn Player<Error = ServoMediaError>);
|
unsafe_no_jsmanaged_fields!(dyn Player<Error = ServoMediaError>);
|
||||||
unsafe_no_jsmanaged_fields!(Mutex<MediaFrameRenderer>);
|
unsafe_no_jsmanaged_fields!(Mutex<MediaFrameRenderer>);
|
||||||
unsafe_no_jsmanaged_fields!(RenderApiSender);
|
unsafe_no_jsmanaged_fields!(RenderApiSender);
|
||||||
|
unsafe_no_jsmanaged_fields!(ResourceFetchTiming);
|
||||||
|
|
||||||
unsafe impl<'a> JSTraceable for &'a str {
|
unsafe impl<'a> JSTraceable for &'a str {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -356,6 +356,8 @@ pub struct Document {
|
||||||
top_level_dom_complete: Cell<u64>,
|
top_level_dom_complete: Cell<u64>,
|
||||||
load_event_start: Cell<u64>,
|
load_event_start: Cell<u64>,
|
||||||
load_event_end: Cell<u64>,
|
load_event_end: Cell<u64>,
|
||||||
|
unload_event_start: Cell<u64>,
|
||||||
|
unload_event_end: Cell<u64>,
|
||||||
/// <https://html.spec.whatwg.org/multipage/#concept-document-https-state>
|
/// <https://html.spec.whatwg.org/multipage/#concept-document-https-state>
|
||||||
https_state: Cell<HttpsState>,
|
https_state: Cell<HttpsState>,
|
||||||
/// The document's origin.
|
/// The document's origin.
|
||||||
|
@ -406,6 +408,8 @@ pub struct Document {
|
||||||
fired_unload: Cell<bool>,
|
fired_unload: Cell<bool>,
|
||||||
/// List of responsive images
|
/// List of responsive images
|
||||||
responsive_images: DomRefCell<Vec<Dom<HTMLImageElement>>>,
|
responsive_images: DomRefCell<Vec<Dom<HTMLImageElement>>>,
|
||||||
|
/// Number of redirects for the document load
|
||||||
|
redirect_count: Cell<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(JSTraceable, MallocSizeOf)]
|
#[derive(JSTraceable, MallocSizeOf)]
|
||||||
|
@ -2290,6 +2294,14 @@ impl Document {
|
||||||
self.load_event_end.get()
|
self.load_event_end.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_unload_event_start(&self) -> u64 {
|
||||||
|
self.unload_event_start.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_unload_event_end(&self) -> u64 {
|
||||||
|
self.unload_event_end.get()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn start_tti(&self) {
|
pub fn start_tti(&self) {
|
||||||
if self.get_interactive_metrics().needs_tti() {
|
if self.get_interactive_metrics().needs_tti() {
|
||||||
self.tti_window.borrow_mut().start_window();
|
self.tti_window.borrow_mut().start_window();
|
||||||
|
@ -2654,6 +2666,8 @@ impl Document {
|
||||||
top_level_dom_complete: Cell::new(Default::default()),
|
top_level_dom_complete: Cell::new(Default::default()),
|
||||||
load_event_start: Cell::new(Default::default()),
|
load_event_start: Cell::new(Default::default()),
|
||||||
load_event_end: Cell::new(Default::default()),
|
load_event_end: Cell::new(Default::default()),
|
||||||
|
unload_event_start: Cell::new(Default::default()),
|
||||||
|
unload_event_end: Cell::new(Default::default()),
|
||||||
https_state: Cell::new(HttpsState::None),
|
https_state: Cell::new(HttpsState::None),
|
||||||
origin: origin,
|
origin: origin,
|
||||||
referrer: referrer,
|
referrer: referrer,
|
||||||
|
@ -2674,6 +2688,7 @@ impl Document {
|
||||||
salvageable: Cell::new(true),
|
salvageable: Cell::new(true),
|
||||||
fired_unload: Cell::new(false),
|
fired_unload: Cell::new(false),
|
||||||
responsive_images: Default::default(),
|
responsive_images: Default::default(),
|
||||||
|
redirect_count: Cell::new(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2739,6 +2754,14 @@ impl Document {
|
||||||
document
|
document
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_redirect_count(&self) -> u16 {
|
||||||
|
self.redirect_count.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_redirect_count(&self, count: u16) {
|
||||||
|
self.redirect_count.set(count)
|
||||||
|
}
|
||||||
|
|
||||||
fn create_node_list<F: Fn(&Node) -> bool>(&self, callback: F) -> DomRoot<NodeList> {
|
fn create_node_list<F: Fn(&Node) -> bool>(&self, callback: F) -> DomRoot<NodeList> {
|
||||||
let doc = self.GetDocumentElement();
|
let doc = self.GetDocumentElement();
|
||||||
let maybe_node = doc.r().map(Castable::upcast::<Node>);
|
let maybe_node = doc.r().map(Castable::upcast::<Node>);
|
||||||
|
@ -4268,6 +4291,9 @@ impl DocumentMethods for Document {
|
||||||
return Ok(DomRoot::from_ref(self));
|
return Ok(DomRoot::from_ref(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: prompt to unload.
|
||||||
|
// TODO: set unload_event_start and unload_event_end
|
||||||
|
|
||||||
window_from_node(self).set_navigation_start();
|
window_from_node(self).set_navigation_start();
|
||||||
|
|
||||||
// Step 7
|
// Step 7
|
||||||
|
|
|
@ -16,8 +16,9 @@ use crate::dom::event::Event;
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::messageevent::MessageEvent;
|
use crate::dom::messageevent::MessageEvent;
|
||||||
|
use crate::dom::performanceresourcetiming::InitiatorType;
|
||||||
use crate::fetch::FetchCanceller;
|
use crate::fetch::FetchCanceller;
|
||||||
use crate::network_listener::{NetworkListener, PreInvoke};
|
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||||
use crate::task_source::{TaskSource, TaskSourceName};
|
use crate::task_source::{TaskSource, TaskSourceName};
|
||||||
use crate::timers::OneshotTimerCallback;
|
use crate::timers::OneshotTimerCallback;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
@ -34,6 +35,7 @@ use net_traits::request::{CacheMode, CorsSettings, CredentialsMode};
|
||||||
use net_traits::request::{RequestInit, RequestMode};
|
use net_traits::request::{RequestInit, RequestMode};
|
||||||
use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata};
|
use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata};
|
||||||
use net_traits::{FetchResponseListener, FetchResponseMsg, NetworkError};
|
use net_traits::{FetchResponseListener, FetchResponseMsg, NetworkError};
|
||||||
|
use net_traits::{ResourceFetchTiming, ResourceTimingType};
|
||||||
use servo_atoms::Atom;
|
use servo_atoms::Atom;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
@ -91,6 +93,8 @@ struct EventSourceContext {
|
||||||
event_type: String,
|
event_type: String,
|
||||||
data: String,
|
data: String,
|
||||||
last_event_id: String,
|
last_event_id: String,
|
||||||
|
|
||||||
|
resource_timing: ResourceFetchTiming,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventSourceContext {
|
impl EventSourceContext {
|
||||||
|
@ -398,12 +402,34 @@ impl FetchResponseListener for EventSourceContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_response_eof(&mut self, _response: Result<(), NetworkError>) {
|
fn process_response_eof(&mut self, _response: Result<ResourceFetchTiming, NetworkError>) {
|
||||||
if let Some(_) = self.incomplete_utf8.take() {
|
if let Some(_) = self.incomplete_utf8.take() {
|
||||||
self.parse("\u{FFFD}".chars());
|
self.parse("\u{FFFD}".chars());
|
||||||
}
|
}
|
||||||
self.reestablish_the_connection();
|
self.reestablish_the_connection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming {
|
||||||
|
&mut self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing(&self) -> &ResourceFetchTiming {
|
||||||
|
&self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn submit_resource_timing(&mut self) {
|
||||||
|
network_listener::submit_timing(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceTimingListener for EventSourceContext {
|
||||||
|
fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
|
||||||
|
(InitiatorType::Other, self.event_source.root().url().clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing_global(&self) -> DomRoot<GlobalScope> {
|
||||||
|
self.event_source.root().global()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreInvoke for EventSourceContext {
|
impl PreInvoke for EventSourceContext {
|
||||||
|
@ -463,6 +489,10 @@ impl EventSource {
|
||||||
self.request.borrow().clone().unwrap()
|
self.request.borrow().clone().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn url(&self) -> &ServoUrl {
|
||||||
|
&self.url
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-eventsource
|
// https://html.spec.whatwg.org/multipage/#dom-eventsource
|
||||||
pub fn Constructor(
|
pub fn Constructor(
|
||||||
global: &GlobalScope,
|
global: &GlobalScope,
|
||||||
|
@ -533,6 +563,7 @@ impl EventSource {
|
||||||
event_type: String::new(),
|
event_type: String::new(),
|
||||||
data: String::new(),
|
data: String::new(),
|
||||||
last_event_id: String::new(),
|
last_event_id: String::new(),
|
||||||
|
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
|
||||||
};
|
};
|
||||||
let listener = NetworkListener {
|
let listener = NetworkListener {
|
||||||
context: Arc::new(Mutex::new(context)),
|
context: Arc::new(Mutex::new(context)),
|
||||||
|
|
|
@ -25,6 +25,7 @@ use crate::dom::element::{reflect_cross_origin_attribute, set_cross_origin_attri
|
||||||
use crate::dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
|
use crate::dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
|
||||||
use crate::dom::event::{Event, EventBubbles, EventCancelable};
|
use crate::dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::htmlareaelement::HTMLAreaElement;
|
use crate::dom::htmlareaelement::HTMLAreaElement;
|
||||||
use crate::dom::htmlelement::HTMLElement;
|
use crate::dom::htmlelement::HTMLElement;
|
||||||
use crate::dom::htmlformelement::{FormControl, HTMLFormElement};
|
use crate::dom::htmlformelement::{FormControl, HTMLFormElement};
|
||||||
|
@ -33,15 +34,17 @@ use crate::dom::htmlpictureelement::HTMLPictureElement;
|
||||||
use crate::dom::htmlsourceelement::HTMLSourceElement;
|
use crate::dom::htmlsourceelement::HTMLSourceElement;
|
||||||
use crate::dom::mouseevent::MouseEvent;
|
use crate::dom::mouseevent::MouseEvent;
|
||||||
use crate::dom::node::{document_from_node, window_from_node, Node, NodeDamage, UnbindContext};
|
use crate::dom::node::{document_from_node, window_from_node, Node, NodeDamage, UnbindContext};
|
||||||
|
use crate::dom::performanceresourcetiming::InitiatorType;
|
||||||
use crate::dom::progressevent::ProgressEvent;
|
use crate::dom::progressevent::ProgressEvent;
|
||||||
use crate::dom::values::UNSIGNED_LONG_MAX;
|
use crate::dom::values::UNSIGNED_LONG_MAX;
|
||||||
use crate::dom::virtualmethods::VirtualMethods;
|
use crate::dom::virtualmethods::VirtualMethods;
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
use crate::microtask::{Microtask, MicrotaskRunnable};
|
use crate::microtask::{Microtask, MicrotaskRunnable};
|
||||||
use crate::network_listener::{NetworkListener, PreInvoke};
|
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||||
use crate::script_thread::ScriptThread;
|
use crate::script_thread::ScriptThread;
|
||||||
use crate::task_source::TaskSource;
|
use crate::task_source::TaskSource;
|
||||||
use cssparser::{Parser, ParserInput};
|
use cssparser::{Parser, ParserInput};
|
||||||
|
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use euclid::Point2D;
|
use euclid::Point2D;
|
||||||
use html5ever::{LocalName, Prefix};
|
use html5ever::{LocalName, Prefix};
|
||||||
|
@ -54,6 +57,7 @@ use net_traits::image_cache::{CanRequestImages, ImageCache, ImageOrMetadataAvail
|
||||||
use net_traits::image_cache::{ImageResponder, ImageResponse, ImageState, PendingImageId};
|
use net_traits::image_cache::{ImageResponder, ImageResponse, ImageState, PendingImageId};
|
||||||
use net_traits::request::RequestInit;
|
use net_traits::request::RequestInit;
|
||||||
use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError};
|
use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError};
|
||||||
|
use net_traits::{ResourceFetchTiming, ResourceTimingType};
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
use servo_url::origin::MutableOrigin;
|
use servo_url::origin::MutableOrigin;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
|
@ -164,6 +168,11 @@ struct ImageContext {
|
||||||
id: PendingImageId,
|
id: PendingImageId,
|
||||||
/// Used to mark abort
|
/// Used to mark abort
|
||||||
aborted: Cell<bool>,
|
aborted: Cell<bool>,
|
||||||
|
/// The document associated with this request
|
||||||
|
doc: Trusted<Document>,
|
||||||
|
/// timing data for this resource
|
||||||
|
resource_timing: ResourceFetchTiming,
|
||||||
|
url: ServoUrl,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FetchResponseListener for ImageContext {
|
impl FetchResponseListener for ImageContext {
|
||||||
|
@ -213,10 +222,35 @@ impl FetchResponseListener for ImageContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
|
fn process_response_eof(&mut self, response: Result<ResourceFetchTiming, NetworkError>) {
|
||||||
self.image_cache
|
self.image_cache
|
||||||
.notify_pending_response(self.id, FetchResponseMsg::ProcessResponseEOF(response));
|
.notify_pending_response(self.id, FetchResponseMsg::ProcessResponseEOF(response));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming {
|
||||||
|
&mut self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing(&self) -> &ResourceFetchTiming {
|
||||||
|
&self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn submit_resource_timing(&mut self) {
|
||||||
|
network_listener::submit_timing(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceTimingListener for ImageContext {
|
||||||
|
fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
|
||||||
|
(
|
||||||
|
InitiatorType::LocalName("img".to_string()),
|
||||||
|
self.url.clone(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing_global(&self) -> DomRoot<GlobalScope> {
|
||||||
|
self.doc.root().global()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreInvoke for ImageContext {
|
impl PreInvoke for ImageContext {
|
||||||
|
@ -306,6 +340,9 @@ impl HTMLImageElement {
|
||||||
status: Ok(()),
|
status: Ok(()),
|
||||||
id: id,
|
id: id,
|
||||||
aborted: Cell::new(false),
|
aborted: Cell::new(false),
|
||||||
|
doc: Trusted::new(&document),
|
||||||
|
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
|
||||||
|
url: img_url.clone(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||||
|
|
|
@ -25,16 +25,18 @@ use crate::dom::blob::Blob;
|
||||||
use crate::dom::document::Document;
|
use crate::dom::document::Document;
|
||||||
use crate::dom::element::{AttributeMutation, Element};
|
use crate::dom::element::{AttributeMutation, Element};
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::htmlelement::HTMLElement;
|
use crate::dom::htmlelement::HTMLElement;
|
||||||
use crate::dom::htmlsourceelement::HTMLSourceElement;
|
use crate::dom::htmlsourceelement::HTMLSourceElement;
|
||||||
use crate::dom::htmlvideoelement::HTMLVideoElement;
|
use crate::dom::htmlvideoelement::HTMLVideoElement;
|
||||||
use crate::dom::mediaerror::MediaError;
|
use crate::dom::mediaerror::MediaError;
|
||||||
use crate::dom::node::{document_from_node, window_from_node, Node, NodeDamage, UnbindContext};
|
use crate::dom::node::{document_from_node, window_from_node, Node, NodeDamage, UnbindContext};
|
||||||
|
use crate::dom::performanceresourcetiming::InitiatorType;
|
||||||
use crate::dom::promise::Promise;
|
use crate::dom::promise::Promise;
|
||||||
use crate::dom::virtualmethods::VirtualMethods;
|
use crate::dom::virtualmethods::VirtualMethods;
|
||||||
use crate::fetch::FetchCanceller;
|
use crate::fetch::FetchCanceller;
|
||||||
use crate::microtask::{Microtask, MicrotaskRunnable};
|
use crate::microtask::{Microtask, MicrotaskRunnable};
|
||||||
use crate::network_listener::{NetworkListener, PreInvoke};
|
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||||
use crate::script_thread::ScriptThread;
|
use crate::script_thread::ScriptThread;
|
||||||
use crate::task_source::TaskSource;
|
use crate::task_source::TaskSource;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
|
@ -46,8 +48,8 @@ use ipc_channel::ipc;
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use mime::{self, Mime};
|
use mime::{self, Mime};
|
||||||
use net_traits::request::{CredentialsMode, Destination, RequestInit};
|
use net_traits::request::{CredentialsMode, Destination, RequestInit};
|
||||||
use net_traits::NetworkError;
|
|
||||||
use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseListener, Metadata};
|
use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseListener, Metadata};
|
||||||
|
use net_traits::{NetworkError, ResourceFetchTiming, ResourceTimingType};
|
||||||
use script_layout_interface::HTMLMediaData;
|
use script_layout_interface::HTMLMediaData;
|
||||||
use servo_media::player::frame::{Frame, FrameRenderer};
|
use servo_media::player::frame::{Frame, FrameRenderer};
|
||||||
use servo_media::player::{PlaybackState, Player, PlayerEvent, StreamType};
|
use servo_media::player::{PlaybackState, Player, PlayerEvent, StreamType};
|
||||||
|
@ -706,7 +708,10 @@ impl HTMLMediaElement {
|
||||||
..RequestInit::default()
|
..RequestInit::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let context = Arc::new(Mutex::new(HTMLMediaElementContext::new(self)));
|
let context = Arc::new(Mutex::new(HTMLMediaElementContext::new(
|
||||||
|
self,
|
||||||
|
self.resource_url.borrow().as_ref().unwrap().clone(),
|
||||||
|
)));
|
||||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||||
let window = window_from_node(self);
|
let window = window_from_node(self);
|
||||||
let (task_source, canceller) = window
|
let (task_source, canceller) = window
|
||||||
|
@ -1459,6 +1464,10 @@ struct HTMLMediaElementContext {
|
||||||
next_progress_event: Timespec,
|
next_progress_event: Timespec,
|
||||||
/// True if this response is invalid and should be ignored.
|
/// True if this response is invalid and should be ignored.
|
||||||
ignore_response: bool,
|
ignore_response: bool,
|
||||||
|
/// timing data for this resource
|
||||||
|
resource_timing: ResourceFetchTiming,
|
||||||
|
/// url for the resource
|
||||||
|
url: ServoUrl,
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list
|
// https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list
|
||||||
|
@ -1527,7 +1536,7 @@ impl FetchResponseListener for HTMLMediaElementContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list
|
// https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list
|
||||||
fn process_response_eof(&mut self, status: Result<(), NetworkError>) {
|
fn process_response_eof(&mut self, status: Result<ResourceFetchTiming, NetworkError>) {
|
||||||
if self.ignore_response {
|
if self.ignore_response {
|
||||||
// An error was received previously, skip processing the payload.
|
// An error was received previously, skip processing the payload.
|
||||||
return;
|
return;
|
||||||
|
@ -1579,6 +1588,35 @@ impl FetchResponseListener for HTMLMediaElementContext {
|
||||||
elem.queue_dedicated_media_source_failure_steps();
|
elem.queue_dedicated_media_source_failure_steps();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming {
|
||||||
|
&mut self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing(&self) -> &ResourceFetchTiming {
|
||||||
|
&self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn submit_resource_timing(&mut self) {
|
||||||
|
network_listener::submit_timing(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceTimingListener for HTMLMediaElementContext {
|
||||||
|
fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
|
||||||
|
let initiator_type = InitiatorType::LocalName(
|
||||||
|
self.elem
|
||||||
|
.root()
|
||||||
|
.upcast::<Element>()
|
||||||
|
.local_name()
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
(initiator_type, self.url.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing_global(&self) -> DomRoot<GlobalScope> {
|
||||||
|
(document_from_node(&*self.elem.root()).global())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreInvoke for HTMLMediaElementContext {
|
impl PreInvoke for HTMLMediaElementContext {
|
||||||
|
@ -1589,13 +1627,15 @@ impl PreInvoke for HTMLMediaElementContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HTMLMediaElementContext {
|
impl HTMLMediaElementContext {
|
||||||
fn new(elem: &HTMLMediaElement) -> HTMLMediaElementContext {
|
fn new(elem: &HTMLMediaElement, url: ServoUrl) -> HTMLMediaElementContext {
|
||||||
HTMLMediaElementContext {
|
HTMLMediaElementContext {
|
||||||
elem: Trusted::new(elem),
|
elem: Trusted::new(elem),
|
||||||
metadata: None,
|
metadata: None,
|
||||||
generation_id: elem.generation_id.get(),
|
generation_id: elem.generation_id.get(),
|
||||||
next_progress_event: time::get_time() + Duration::milliseconds(350),
|
next_progress_event: time::get_time() + Duration::milliseconds(350),
|
||||||
ignore_response: false,
|
ignore_response: false,
|
||||||
|
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
|
||||||
|
url: url,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,9 @@ use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::htmlelement::HTMLElement;
|
use crate::dom::htmlelement::HTMLElement;
|
||||||
use crate::dom::node::{document_from_node, window_from_node};
|
use crate::dom::node::{document_from_node, window_from_node};
|
||||||
use crate::dom::node::{ChildrenMutation, CloneChildrenFlag, Node};
|
use crate::dom::node::{ChildrenMutation, CloneChildrenFlag, Node};
|
||||||
|
use crate::dom::performanceresourcetiming::InitiatorType;
|
||||||
use crate::dom::virtualmethods::VirtualMethods;
|
use crate::dom::virtualmethods::VirtualMethods;
|
||||||
use crate::network_listener::{NetworkListener, PreInvoke};
|
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use encoding_rs::Encoding;
|
use encoding_rs::Encoding;
|
||||||
use html5ever::{LocalName, Prefix};
|
use html5ever::{LocalName, Prefix};
|
||||||
|
@ -33,6 +34,7 @@ use ipc_channel::router::ROUTER;
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestInit, RequestMode};
|
use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestInit, RequestMode};
|
||||||
use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
|
use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
|
||||||
|
use net_traits::{ResourceFetchTiming, ResourceTimingType};
|
||||||
use servo_atoms::Atom;
|
use servo_atoms::Atom;
|
||||||
use servo_config::opts;
|
use servo_config::opts;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
|
@ -166,6 +168,8 @@ struct ScriptContext {
|
||||||
url: ServoUrl,
|
url: ServoUrl,
|
||||||
/// Indicates whether the request failed, and why
|
/// Indicates whether the request failed, and why
|
||||||
status: Result<(), NetworkError>,
|
status: Result<(), NetworkError>,
|
||||||
|
/// Timing object for this resource
|
||||||
|
resource_timing: ResourceFetchTiming,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FetchResponseListener for ScriptContext {
|
impl FetchResponseListener for ScriptContext {
|
||||||
|
@ -208,7 +212,7 @@ impl FetchResponseListener for ScriptContext {
|
||||||
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#fetch-a-classic-script>
|
/// <https://html.spec.whatwg.org/multipage/#fetch-a-classic-script>
|
||||||
/// step 4-9
|
/// step 4-9
|
||||||
fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
|
fn process_response_eof(&mut self, response: Result<ResourceFetchTiming, NetworkError>) {
|
||||||
// Step 5.
|
// Step 5.
|
||||||
let load = response.and(self.status.clone()).map(|_| {
|
let load = response.and(self.status.clone()).map(|_| {
|
||||||
let metadata = self.metadata.take().unwrap();
|
let metadata = self.metadata.take().unwrap();
|
||||||
|
@ -241,6 +245,35 @@ impl FetchResponseListener for ScriptContext {
|
||||||
|
|
||||||
document.finish_load(LoadType::Script(self.url.clone()));
|
document.finish_load(LoadType::Script(self.url.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming {
|
||||||
|
&mut self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing(&self) -> &ResourceFetchTiming {
|
||||||
|
&self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn submit_resource_timing(&mut self) {
|
||||||
|
network_listener::submit_timing(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceTimingListener for ScriptContext {
|
||||||
|
fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
|
||||||
|
let initiator_type = InitiatorType::LocalName(
|
||||||
|
self.elem
|
||||||
|
.root()
|
||||||
|
.upcast::<Element>()
|
||||||
|
.local_name()
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
(initiator_type, self.url.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing_global(&self) -> DomRoot<GlobalScope> {
|
||||||
|
(document_from_node(&*self.elem.root()).global())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreInvoke for ScriptContext {}
|
impl PreInvoke for ScriptContext {}
|
||||||
|
@ -290,6 +323,7 @@ fn fetch_a_classic_script(
|
||||||
metadata: None,
|
metadata: None,
|
||||||
url: url.clone(),
|
url: url.clone(),
|
||||||
status: Ok(()),
|
status: Ok(()),
|
||||||
|
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||||
|
|
|
@ -415,10 +415,11 @@ pub mod performance;
|
||||||
pub mod performanceentry;
|
pub mod performanceentry;
|
||||||
pub mod performancemark;
|
pub mod performancemark;
|
||||||
pub mod performancemeasure;
|
pub mod performancemeasure;
|
||||||
|
pub mod performancenavigationtiming;
|
||||||
pub mod performanceobserver;
|
pub mod performanceobserver;
|
||||||
pub mod performanceobserverentrylist;
|
pub mod performanceobserverentrylist;
|
||||||
pub mod performancepainttiming;
|
pub mod performancepainttiming;
|
||||||
pub mod performancetiming;
|
pub mod performanceresourcetiming;
|
||||||
pub mod permissions;
|
pub mod permissions;
|
||||||
pub mod permissionstatus;
|
pub mod permissionstatus;
|
||||||
pub mod plugin;
|
pub mod plugin;
|
||||||
|
|
|
@ -11,15 +11,16 @@ use crate::dom::bindings::codegen::Bindings::PerformanceBinding::{
|
||||||
use crate::dom::bindings::error::{Error, Fallible};
|
use crate::dom::bindings::error::{Error, Fallible};
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::num::Finite;
|
use crate::dom::bindings::num::Finite;
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
|
use crate::dom::eventtarget::EventTarget;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::performanceentry::PerformanceEntry;
|
use crate::dom::performanceentry::PerformanceEntry;
|
||||||
use crate::dom::performancemark::PerformanceMark;
|
use crate::dom::performancemark::PerformanceMark;
|
||||||
use crate::dom::performancemeasure::PerformanceMeasure;
|
use crate::dom::performancemeasure::PerformanceMeasure;
|
||||||
|
use crate::dom::performancenavigationtiming::PerformanceNavigationTiming;
|
||||||
use crate::dom::performanceobserver::PerformanceObserver as DOMPerformanceObserver;
|
use crate::dom::performanceobserver::PerformanceObserver as DOMPerformanceObserver;
|
||||||
use crate::dom::performancetiming::PerformanceTiming;
|
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use metrics::ToMs;
|
use metrics::ToMs;
|
||||||
|
@ -131,8 +132,7 @@ struct PerformanceObserver {
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct Performance {
|
pub struct Performance {
|
||||||
reflector_: Reflector,
|
eventtarget: EventTarget,
|
||||||
timing: Option<Dom<PerformanceTiming>>,
|
|
||||||
entries: DomRefCell<PerformanceEntryList>,
|
entries: DomRefCell<PerformanceEntryList>,
|
||||||
observers: DomRefCell<Vec<PerformanceObserver>>,
|
observers: DomRefCell<Vec<PerformanceObserver>>,
|
||||||
pending_notification_observers_task: Cell<bool>,
|
pending_notification_observers_task: Cell<bool>,
|
||||||
|
@ -140,22 +140,9 @@ pub struct Performance {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Performance {
|
impl Performance {
|
||||||
fn new_inherited(
|
fn new_inherited(navigation_start_precise: u64) -> Performance {
|
||||||
global: &GlobalScope,
|
|
||||||
navigation_start: u64,
|
|
||||||
navigation_start_precise: u64,
|
|
||||||
) -> Performance {
|
|
||||||
Performance {
|
Performance {
|
||||||
reflector_: Reflector::new(),
|
eventtarget: EventTarget::new_inherited(),
|
||||||
timing: if global.is::<Window>() {
|
|
||||||
Some(Dom::from_ref(&*PerformanceTiming::new(
|
|
||||||
global.as_window(),
|
|
||||||
navigation_start,
|
|
||||||
navigation_start_precise,
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
entries: DomRefCell::new(PerformanceEntryList::new(Vec::new())),
|
entries: DomRefCell::new(PerformanceEntryList::new(Vec::new())),
|
||||||
observers: DomRefCell::new(Vec::new()),
|
observers: DomRefCell::new(Vec::new()),
|
||||||
pending_notification_observers_task: Cell::new(false),
|
pending_notification_observers_task: Cell::new(false),
|
||||||
|
@ -163,17 +150,9 @@ impl Performance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(global: &GlobalScope, navigation_start_precise: u64) -> DomRoot<Performance> {
|
||||||
global: &GlobalScope,
|
|
||||||
navigation_start: u64,
|
|
||||||
navigation_start_precise: u64,
|
|
||||||
) -> DomRoot<Performance> {
|
|
||||||
reflect_dom_object(
|
reflect_dom_object(
|
||||||
Box::new(Performance::new_inherited(
|
Box::new(Performance::new_inherited(navigation_start_precise)),
|
||||||
global,
|
|
||||||
navigation_start,
|
|
||||||
navigation_start_precise,
|
|
||||||
)),
|
|
||||||
global,
|
global,
|
||||||
PerformanceBinding::Wrap,
|
PerformanceBinding::Wrap,
|
||||||
)
|
)
|
||||||
|
@ -296,21 +275,23 @@ impl Performance {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn now(&self) -> f64 {
|
fn now(&self) -> f64 {
|
||||||
let nav_start = match self.timing {
|
(time::precise_time_ns() - self.navigation_start_precise).to_ms()
|
||||||
Some(ref timing) => timing.navigation_start_precise(),
|
|
||||||
None => self.navigation_start_precise,
|
|
||||||
};
|
|
||||||
(time::precise_time_ns() - nav_start).to_ms()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PerformanceMethods for Performance {
|
impl PerformanceMethods for Performance {
|
||||||
|
// FIXME(avada): this should be deprecated in the future, but some sites still use it
|
||||||
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html#performance-timing-attribute
|
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html#performance-timing-attribute
|
||||||
fn Timing(&self) -> DomRoot<PerformanceTiming> {
|
fn Timing(&self) -> DomRoot<PerformanceNavigationTiming> {
|
||||||
match self.timing {
|
let entries = self.GetEntriesByType(DOMString::from("navigation"));
|
||||||
Some(ref timing) => DomRoot::from_ref(&*timing),
|
if entries.len() > 0 {
|
||||||
None => unreachable!("Are we trying to expose Performance.timing in workers?"),
|
return DomRoot::from_ref(
|
||||||
|
entries[0]
|
||||||
|
.downcast::<PerformanceNavigationTiming>()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
unreachable!("Are we trying to expose Performance.timing in workers?");
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HighResolutionTime/Overview.html#dom-performance-now
|
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HighResolutionTime/Overview.html#dom-performance-now
|
||||||
|
@ -318,6 +299,11 @@ impl PerformanceMethods for Performance {
|
||||||
Finite::wrap(self.now())
|
Finite::wrap(self.now())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/hr-time-2/#dom-performance-timeorigin
|
||||||
|
fn TimeOrigin(&self) -> DOMHighResTimeStamp {
|
||||||
|
Finite::wrap(self.navigation_start_precise as f64)
|
||||||
|
}
|
||||||
|
|
||||||
// https://www.w3.org/TR/performance-timeline-2/#dom-performance-getentries
|
// https://www.w3.org/TR/performance-timeline-2/#dom-performance-getentries
|
||||||
fn GetEntries(&self) -> Vec<DomRoot<PerformanceEntry>> {
|
fn GetEntries(&self) -> Vec<DomRoot<PerformanceEntry>> {
|
||||||
self.entries
|
self.entries
|
||||||
|
|
|
@ -59,6 +59,10 @@ impl PerformanceEntry {
|
||||||
pub fn start_time(&self) -> f64 {
|
pub fn start_time(&self) -> f64 {
|
||||||
self.start_time
|
self.start_time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn duration(&self) -> f64 {
|
||||||
|
self.duration
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PerformanceEntryMethods for PerformanceEntry {
|
impl PerformanceEntryMethods for PerformanceEntry {
|
||||||
|
|
126
components/script/dom/performancenavigationtiming.rs
Normal file
126
components/script/dom/performancenavigationtiming.rs
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::dom::bindings::codegen::Bindings::PerformanceBinding::DOMHighResTimeStamp;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::PerformanceNavigationTimingBinding::PerformanceNavigationTimingMethods;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::PerformanceNavigationTimingBinding::{
|
||||||
|
self, NavigationType,
|
||||||
|
};
|
||||||
|
use crate::dom::bindings::num::Finite;
|
||||||
|
use crate::dom::bindings::reflector::reflect_dom_object;
|
||||||
|
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||||
|
use crate::dom::document::Document;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::performanceresourcetiming::{InitiatorType, PerformanceResourceTiming};
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming
|
||||||
|
/// Only the current document resource is included in the performance timeline;
|
||||||
|
/// there is only one PerformanceNavigationTiming object in the performance timeline.
|
||||||
|
pub struct PerformanceNavigationTiming {
|
||||||
|
// https://w3c.github.io/navigation-timing/#PerformanceResourceTiming
|
||||||
|
performanceresourcetiming: PerformanceResourceTiming,
|
||||||
|
navigation_start: u64,
|
||||||
|
navigation_start_precise: u64,
|
||||||
|
document: Dom<Document>,
|
||||||
|
nav_type: NavigationType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PerformanceNavigationTiming {
|
||||||
|
fn new_inherited(
|
||||||
|
nav_start: u64,
|
||||||
|
nav_start_precise: u64,
|
||||||
|
document: &Document,
|
||||||
|
) -> PerformanceNavigationTiming {
|
||||||
|
PerformanceNavigationTiming {
|
||||||
|
performanceresourcetiming: PerformanceResourceTiming::new_inherited(
|
||||||
|
document.url(),
|
||||||
|
InitiatorType::Navigation,
|
||||||
|
None,
|
||||||
|
nav_start_precise as f64,
|
||||||
|
),
|
||||||
|
navigation_start: nav_start,
|
||||||
|
navigation_start_precise: nav_start_precise,
|
||||||
|
document: Dom::from_ref(document),
|
||||||
|
nav_type: NavigationType::Navigate,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
global: &GlobalScope,
|
||||||
|
nav_start: u64,
|
||||||
|
nav_start_precise: u64,
|
||||||
|
document: &Document,
|
||||||
|
) -> DomRoot<PerformanceNavigationTiming> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(PerformanceNavigationTiming::new_inherited(
|
||||||
|
nav_start,
|
||||||
|
nav_start_precise,
|
||||||
|
document,
|
||||||
|
)),
|
||||||
|
global,
|
||||||
|
PerformanceNavigationTimingBinding::Wrap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/navigation-timing/
|
||||||
|
impl PerformanceNavigationTimingMethods for PerformanceNavigationTiming {
|
||||||
|
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-unloadeventstart
|
||||||
|
fn UnloadEventStart(&self) -> DOMHighResTimeStamp {
|
||||||
|
Finite::wrap(self.document.get_unload_event_start() as f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-unloadeventend
|
||||||
|
fn UnloadEventEnd(&self) -> DOMHighResTimeStamp {
|
||||||
|
Finite::wrap(self.document.get_unload_event_end() as f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-dominteractive
|
||||||
|
fn DomInteractive(&self) -> DOMHighResTimeStamp {
|
||||||
|
Finite::wrap(self.document.get_dom_interactive() as f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-domcontentloadedeventstart
|
||||||
|
fn DomContentLoadedEventStart(&self) -> DOMHighResTimeStamp {
|
||||||
|
Finite::wrap(self.document.get_dom_content_loaded_event_start() as f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-domcontentloadedeventstart
|
||||||
|
fn DomContentLoadedEventEnd(&self) -> DOMHighResTimeStamp {
|
||||||
|
Finite::wrap(self.document.get_dom_content_loaded_event_end() as f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-domcomplete
|
||||||
|
fn DomComplete(&self) -> DOMHighResTimeStamp {
|
||||||
|
Finite::wrap(self.document.get_dom_complete() as f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-loadeventstart
|
||||||
|
fn LoadEventStart(&self) -> DOMHighResTimeStamp {
|
||||||
|
Finite::wrap(self.document.get_load_event_start() as f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-loadeventend
|
||||||
|
fn LoadEventEnd(&self) -> DOMHighResTimeStamp {
|
||||||
|
Finite::wrap(self.document.get_load_event_end() as f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-type
|
||||||
|
fn Type(&self) -> NavigationType {
|
||||||
|
self.nav_type.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-redirectcount
|
||||||
|
fn RedirectCount(&self) -> u16 {
|
||||||
|
self.document.get_redirect_count()
|
||||||
|
}
|
||||||
|
|
||||||
|
// check-tidy: no specs after this line
|
||||||
|
// Servo-only timing for when top-level content (not iframes) is complete
|
||||||
|
fn TopLevelDomComplete(&self) -> DOMHighResTimeStamp {
|
||||||
|
Finite::wrap(self.document.get_top_level_dom_complete() as f64)
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,7 +24,9 @@ use std::rc::Rc;
|
||||||
const VALID_ENTRY_TYPES: &'static [&'static str] = &[
|
const VALID_ENTRY_TYPES: &'static [&'static str] = &[
|
||||||
"mark", // User Timing API
|
"mark", // User Timing API
|
||||||
"measure", // User Timing API
|
"measure", // User Timing API
|
||||||
// "resource", XXX Resource Timing API
|
"resource", // Resource Timing API
|
||||||
|
"navigation", // Navigation Timing API
|
||||||
|
// "frame", //TODO Frame Timing API
|
||||||
// "server", XXX Server Timing API
|
// "server", XXX Server Timing API
|
||||||
"paint", // Paint Timing API
|
"paint", // Paint Timing API
|
||||||
];
|
];
|
||||||
|
|
187
components/script/dom/performanceresourcetiming.rs
Normal file
187
components/script/dom/performanceresourcetiming.rs
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::dom::bindings::codegen::Bindings::PerformanceBinding::DOMHighResTimeStamp;
|
||||||
|
use crate::dom::bindings::codegen::Bindings::PerformanceResourceTimingBinding::{
|
||||||
|
self, PerformanceResourceTimingMethods,
|
||||||
|
};
|
||||||
|
use crate::dom::bindings::num::Finite;
|
||||||
|
use crate::dom::bindings::reflector::reflect_dom_object;
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::bindings::str::DOMString;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::performanceentry::PerformanceEntry;
|
||||||
|
use dom_struct::dom_struct;
|
||||||
|
use net_traits::ResourceFetchTiming;
|
||||||
|
use servo_url::ServoUrl;
|
||||||
|
|
||||||
|
// TODO UA may choose to limit how many resources are included as PerformanceResourceTiming objects
|
||||||
|
// recommended minimum is 150, can be changed by setResourceTimingBufferSize in performance
|
||||||
|
// https://w3c.github.io/resource-timing/#sec-extensions-performance-interface
|
||||||
|
|
||||||
|
// TODO Cross origin resources MUST BE INCLUDED as PerformanceResourceTiming objects
|
||||||
|
// https://w3c.github.io/resource-timing/#sec-cross-origin-resources
|
||||||
|
|
||||||
|
// TODO CSS, Beacon
|
||||||
|
#[derive(Debug, JSTraceable, MallocSizeOf, PartialEq)]
|
||||||
|
pub enum InitiatorType {
|
||||||
|
LocalName(String),
|
||||||
|
Navigation,
|
||||||
|
XMLHttpRequest,
|
||||||
|
Fetch,
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[dom_struct]
|
||||||
|
pub struct PerformanceResourceTiming {
|
||||||
|
entry: PerformanceEntry,
|
||||||
|
initiator_type: InitiatorType,
|
||||||
|
next_hop: Option<DOMString>,
|
||||||
|
worker_start: f64,
|
||||||
|
redirect_start: f64,
|
||||||
|
redirect_end: f64,
|
||||||
|
fetch_start: f64,
|
||||||
|
domain_lookup_start: f64,
|
||||||
|
domain_lookup_end: f64,
|
||||||
|
connect_start: f64,
|
||||||
|
connect_end: f64,
|
||||||
|
secure_connection_start: f64,
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(#21254): startTime
|
||||||
|
// TODO(#21255): duration
|
||||||
|
// TODO(#21269): next_hop
|
||||||
|
// TODO(#21264): worker_start
|
||||||
|
// TODO(#21256): redirect_start
|
||||||
|
// TODO(#21257): redirect_end
|
||||||
|
// TODO(#21258): fetch_start
|
||||||
|
// TODO(#21259): domain_lookup_start
|
||||||
|
// TODO(#21260): domain_lookup_end
|
||||||
|
// TODO(#21261): connect_start
|
||||||
|
// TODO(#21262): connect_end
|
||||||
|
// TODO(#21263): response_end
|
||||||
|
impl PerformanceResourceTiming {
|
||||||
|
pub fn new_inherited(
|
||||||
|
url: ServoUrl,
|
||||||
|
initiator_type: InitiatorType,
|
||||||
|
next_hop: Option<DOMString>,
|
||||||
|
fetch_start: f64,
|
||||||
|
) -> PerformanceResourceTiming {
|
||||||
|
PerformanceResourceTiming {
|
||||||
|
entry: PerformanceEntry::new_inherited(
|
||||||
|
DOMString::from(url.into_string()),
|
||||||
|
DOMString::from("resource"),
|
||||||
|
fetch_start,
|
||||||
|
0.,
|
||||||
|
),
|
||||||
|
initiator_type: initiator_type,
|
||||||
|
next_hop: next_hop,
|
||||||
|
worker_start: 0.,
|
||||||
|
redirect_start: 0.,
|
||||||
|
redirect_end: 0.,
|
||||||
|
fetch_start: fetch_start,
|
||||||
|
domain_lookup_start: 0.,
|
||||||
|
domain_lookup_end: 0.,
|
||||||
|
connect_start: 0.,
|
||||||
|
connect_end: 0.,
|
||||||
|
secure_connection_start: 0.,
|
||||||
|
request_start: 0.,
|
||||||
|
response_start: 0.,
|
||||||
|
response_end: 0.,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO fetch start should be in RFT
|
||||||
|
#[allow(unrooted_must_root)]
|
||||||
|
fn from_resource_timing(
|
||||||
|
url: ServoUrl,
|
||||||
|
initiator_type: InitiatorType,
|
||||||
|
next_hop: Option<DOMString>,
|
||||||
|
resource_timing: &ResourceFetchTiming,
|
||||||
|
) -> PerformanceResourceTiming {
|
||||||
|
PerformanceResourceTiming {
|
||||||
|
entry: PerformanceEntry::new_inherited(
|
||||||
|
DOMString::from(url.into_string()),
|
||||||
|
DOMString::from("resource"),
|
||||||
|
0.,
|
||||||
|
0.,
|
||||||
|
),
|
||||||
|
initiator_type: initiator_type,
|
||||||
|
next_hop: next_hop,
|
||||||
|
worker_start: 0.,
|
||||||
|
redirect_start: 0.,
|
||||||
|
redirect_end: 0.,
|
||||||
|
fetch_start: 0.,
|
||||||
|
domain_lookup_start: 0.,
|
||||||
|
domain_lookup_end: 0.,
|
||||||
|
connect_start: 0.,
|
||||||
|
connect_end: 0.,
|
||||||
|
secure_connection_start: 0.,
|
||||||
|
request_start: resource_timing.request_start as f64,
|
||||||
|
response_start: resource_timing.response_start as f64,
|
||||||
|
response_end: 0.,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
global: &GlobalScope,
|
||||||
|
url: ServoUrl,
|
||||||
|
initiator_type: InitiatorType,
|
||||||
|
next_hop: Option<DOMString>,
|
||||||
|
resource_timing: &ResourceFetchTiming,
|
||||||
|
) -> DomRoot<PerformanceResourceTiming> {
|
||||||
|
reflect_dom_object(
|
||||||
|
Box::new(PerformanceResourceTiming::from_resource_timing(
|
||||||
|
url,
|
||||||
|
initiator_type,
|
||||||
|
next_hop,
|
||||||
|
resource_timing,
|
||||||
|
)),
|
||||||
|
global,
|
||||||
|
PerformanceResourceTimingBinding::Wrap,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/resource-timing/
|
||||||
|
impl PerformanceResourceTimingMethods for PerformanceResourceTiming {
|
||||||
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-initiatortype
|
||||||
|
fn InitiatorType(&self) -> DOMString {
|
||||||
|
match self.initiator_type {
|
||||||
|
InitiatorType::LocalName(ref n) => DOMString::from(n.clone()),
|
||||||
|
InitiatorType::Navigation => DOMString::from("navigation"),
|
||||||
|
InitiatorType::XMLHttpRequest => DOMString::from("xmlhttprequest"),
|
||||||
|
InitiatorType::Fetch => DOMString::from("fetch"),
|
||||||
|
InitiatorType::Other => DOMString::from("other"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-nexthopprotocol
|
||||||
|
// returns the ALPN protocol ID of the network protocol used to fetch the resource
|
||||||
|
// when a proxy is configured
|
||||||
|
fn NextHopProtocol(&self) -> DOMString {
|
||||||
|
match self.next_hop {
|
||||||
|
Some(ref protocol) => DOMString::from(protocol.clone()),
|
||||||
|
None => DOMString::from(""),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-requeststart
|
||||||
|
fn RequestStart(&self) -> DOMHighResTimeStamp {
|
||||||
|
// TODO
|
||||||
|
Finite::wrap(self.request_start)
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-responsestart
|
||||||
|
fn ResponseStart(&self) -> DOMHighResTimeStamp {
|
||||||
|
// TODO
|
||||||
|
Finite::wrap(self.response_start)
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||||
use crate::dom::bindings::codegen::Bindings::ServoParserBinding;
|
use crate::dom::bindings::codegen::Bindings::ServoParserBinding;
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::refcounted::Trusted;
|
use crate::dom::bindings::refcounted::Trusted;
|
||||||
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||||
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom, RootedReference};
|
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom, RootedReference};
|
||||||
use crate::dom::bindings::settings_stack::is_execution_stack_empty;
|
use crate::dom::bindings::settings_stack::is_execution_stack_empty;
|
||||||
use crate::dom::bindings::str::DOMString;
|
use crate::dom::bindings::str::DOMString;
|
||||||
|
@ -28,6 +28,8 @@ use crate::dom::htmlimageelement::HTMLImageElement;
|
||||||
use crate::dom::htmlscriptelement::{HTMLScriptElement, ScriptResult};
|
use crate::dom::htmlscriptelement::{HTMLScriptElement, ScriptResult};
|
||||||
use crate::dom::htmltemplateelement::HTMLTemplateElement;
|
use crate::dom::htmltemplateelement::HTMLTemplateElement;
|
||||||
use crate::dom::node::Node;
|
use crate::dom::node::Node;
|
||||||
|
use crate::dom::performanceentry::PerformanceEntry;
|
||||||
|
use crate::dom::performancenavigationtiming::PerformanceNavigationTiming;
|
||||||
use crate::dom::processinginstruction::ProcessingInstruction;
|
use crate::dom::processinginstruction::ProcessingInstruction;
|
||||||
use crate::dom::text::Text;
|
use crate::dom::text::Text;
|
||||||
use crate::dom::virtualmethods::vtable_for;
|
use crate::dom::virtualmethods::vtable_for;
|
||||||
|
@ -43,8 +45,10 @@ use hyper_serde::Serde;
|
||||||
use mime::{self, Mime};
|
use mime::{self, Mime};
|
||||||
use msg::constellation_msg::PipelineId;
|
use msg::constellation_msg::PipelineId;
|
||||||
use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
|
use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
|
||||||
use profile_traits::time::{profile, ProfilerCategory, TimerMetadataReflowType};
|
use net_traits::{ResourceFetchTiming, ResourceTimingType};
|
||||||
use profile_traits::time::{TimerMetadata, TimerMetadataFrameType};
|
use profile_traits::time::{
|
||||||
|
profile, ProfilerCategory, TimerMetadata, TimerMetadataFrameType, TimerMetadataReflowType,
|
||||||
|
};
|
||||||
use script_traits::DocumentActivity;
|
use script_traits::DocumentActivity;
|
||||||
use servo_config::prefs::PREFS;
|
use servo_config::prefs::PREFS;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
|
@ -656,6 +660,8 @@ pub struct ParserContext {
|
||||||
id: PipelineId,
|
id: PipelineId,
|
||||||
/// The URL for this document.
|
/// The URL for this document.
|
||||||
url: ServoUrl,
|
url: ServoUrl,
|
||||||
|
/// timing data for this resource
|
||||||
|
resource_timing: ResourceFetchTiming,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParserContext {
|
impl ParserContext {
|
||||||
|
@ -665,6 +671,7 @@ impl ParserContext {
|
||||||
is_synthesized_document: false,
|
is_synthesized_document: false,
|
||||||
id: id,
|
id: id,
|
||||||
url: url,
|
url: url,
|
||||||
|
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Navigation),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -792,7 +799,10 @@ impl FetchResponseListener for ParserContext {
|
||||||
parser.parse_bytes_chunk(payload);
|
parser.parse_bytes_chunk(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_response_eof(&mut self, status: Result<(), NetworkError>) {
|
// This method is called via script_thread::handle_fetch_eof, so we must call
|
||||||
|
// submit_resource_timing in this function
|
||||||
|
// Resource listeners are called via net_traits::Action::process, which handles submission for them
|
||||||
|
fn process_response_eof(&mut self, status: Result<ResourceFetchTiming, NetworkError>) {
|
||||||
let parser = match self.parser.as_ref() {
|
let parser = match self.parser.as_ref() {
|
||||||
Some(parser) => parser.root(),
|
Some(parser) => parser.root(),
|
||||||
None => return,
|
None => return,
|
||||||
|
@ -801,15 +811,53 @@ impl FetchResponseListener for ParserContext {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(err) = status {
|
match status {
|
||||||
|
// are we throwing this away or can we use it?
|
||||||
|
Ok(_) => (),
|
||||||
// TODO(Savago): we should send a notification to callers #5463.
|
// TODO(Savago): we should send a notification to callers #5463.
|
||||||
debug!("Failed to load page URL {}, error: {:?}", self.url, err);
|
Err(err) => debug!("Failed to load page URL {}, error: {:?}", self.url, err),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parser
|
||||||
|
.document
|
||||||
|
.set_redirect_count(self.resource_timing.redirect_count);
|
||||||
|
|
||||||
parser.last_chunk_received.set(true);
|
parser.last_chunk_received.set(true);
|
||||||
if !parser.suspended.get() {
|
if !parser.suspended.get() {
|
||||||
parser.parse_sync();
|
parser.parse_sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO only submit if this is the current document resource
|
||||||
|
self.submit_resource_timing();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming {
|
||||||
|
&mut self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing(&self) -> &ResourceFetchTiming {
|
||||||
|
&self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
// store a PerformanceNavigationTiming entry in the globalscope's Performance buffer
|
||||||
|
fn submit_resource_timing(&mut self) {
|
||||||
|
let parser = match self.parser.as_ref() {
|
||||||
|
Some(parser) => parser.root(),
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
if parser.aborted.get() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let document = &parser.document;
|
||||||
|
|
||||||
|
//TODO nav_start and nav_start_precise
|
||||||
|
let performance_entry =
|
||||||
|
PerformanceNavigationTiming::new(&document.global(), 0, 0, &document);
|
||||||
|
document
|
||||||
|
.global()
|
||||||
|
.performance()
|
||||||
|
.queue_entry(performance_entry.upcast::<PerformanceEntry>(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,10 @@ typedef double DOMHighResTimeStamp;
|
||||||
typedef sequence<PerformanceEntry> PerformanceEntryList;
|
typedef sequence<PerformanceEntry> PerformanceEntryList;
|
||||||
|
|
||||||
[Exposed=(Window, Worker)]
|
[Exposed=(Window, Worker)]
|
||||||
interface Performance {
|
interface Performance : EventTarget {
|
||||||
DOMHighResTimeStamp now();
|
DOMHighResTimeStamp now();
|
||||||
};
|
readonly attribute DOMHighResTimeStamp timeOrigin;
|
||||||
|
// [Default] object toJSON();
|
||||||
[Exposed=(Window)]
|
|
||||||
partial interface Performance {
|
|
||||||
readonly attribute PerformanceTiming timing;
|
|
||||||
/* readonly attribute PerformanceNavigation navigation; */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://w3c.github.io/performance-timeline/#extensions-to-the-performance-interface
|
// https://w3c.github.io/performance-timeline/#extensions-to-the-performance-interface
|
||||||
|
@ -39,3 +35,10 @@ partial interface Performance {
|
||||||
void measure(DOMString measureName, optional DOMString startMark, optional DOMString endMark);
|
void measure(DOMString measureName, optional DOMString startMark, optional DOMString endMark);
|
||||||
void clearMeasures(optional DOMString measureName);
|
void clearMeasures(optional DOMString measureName);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// FIXME(avada): this should be deprecated, but is currently included for web compat
|
||||||
|
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html#performance-timing-attribute
|
||||||
|
[Exposed=(Window)]
|
||||||
|
partial interface Performance {
|
||||||
|
PerformanceNavigationTiming timing();
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||||
|
/*
|
||||||
|
* The origin of this IDL file is
|
||||||
|
* https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum NavigationType {
|
||||||
|
"navigate",
|
||||||
|
"reload",
|
||||||
|
"back_forward",
|
||||||
|
"prerender"
|
||||||
|
};
|
||||||
|
|
||||||
|
[Exposed=Window]
|
||||||
|
interface PerformanceNavigationTiming : PerformanceResourceTiming {
|
||||||
|
readonly attribute DOMHighResTimeStamp unloadEventStart;
|
||||||
|
readonly attribute DOMHighResTimeStamp unloadEventEnd;
|
||||||
|
readonly attribute DOMHighResTimeStamp domInteractive;
|
||||||
|
readonly attribute DOMHighResTimeStamp domContentLoadedEventStart;
|
||||||
|
readonly attribute DOMHighResTimeStamp domContentLoadedEventEnd;
|
||||||
|
readonly attribute DOMHighResTimeStamp domComplete;
|
||||||
|
readonly attribute DOMHighResTimeStamp loadEventStart;
|
||||||
|
readonly attribute DOMHighResTimeStamp loadEventEnd;
|
||||||
|
readonly attribute NavigationType type;
|
||||||
|
readonly attribute unsigned short redirectCount;
|
||||||
|
// [Default] object toJSON();
|
||||||
|
/* Servo-only attribute for measuring when the top-level document (not iframes) is complete. */
|
||||||
|
[Pref="dom.testperf.enabled"]
|
||||||
|
readonly attribute DOMHighResTimeStamp topLevelDomComplete;
|
||||||
|
};
|
|
@ -0,0 +1,35 @@
|
||||||
|
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||||
|
/*
|
||||||
|
* The origin of this IDL file is
|
||||||
|
* https://w3c.github.io/resource-timing/
|
||||||
|
*/
|
||||||
|
|
||||||
|
[Exposed=(Window,Worker)]
|
||||||
|
interface PerformanceResourceTiming : PerformanceEntry {
|
||||||
|
readonly attribute DOMString initiatorType;
|
||||||
|
readonly attribute DOMString nextHopProtocol;
|
||||||
|
// readonly attribute DOMHighResTimeStamp workerStart;
|
||||||
|
// readonly attribute DOMHighResTimeStamp redirectStart;
|
||||||
|
// readonly attribute DOMHighResTimeStamp redirectEnd;
|
||||||
|
// readonly attribute DOMHighResTimeStamp fetchStart;
|
||||||
|
// readonly attribute DOMHighResTimeStamp domainLookupStart;
|
||||||
|
// readonly attribute DOMHighResTimeStamp domainLookupEnd;
|
||||||
|
// readonly attribute DOMHighResTimeStamp connectStart;
|
||||||
|
// readonly attribute DOMHighResTimeStamp connectEnd;
|
||||||
|
// 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;
|
||||||
|
// [Default] object toJSON();
|
||||||
|
};
|
||||||
|
|
||||||
|
// partial interface Performance {
|
||||||
|
// void clearResourceTimings();
|
||||||
|
// void setResourceTimingBufferSize(unsigned long maxSize);
|
||||||
|
// attribute EventHandler onresourcetimingbufferfull;
|
||||||
|
// };
|
|
@ -1,35 +0,0 @@
|
||||||
/* 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/. */
|
|
||||||
/*
|
|
||||||
* The origin of this IDL file is
|
|
||||||
* https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html#sec-navigation-timing-interface
|
|
||||||
*/
|
|
||||||
|
|
||||||
[Exposed=(Window)]
|
|
||||||
interface PerformanceTiming {
|
|
||||||
readonly attribute unsigned long long navigationStart;
|
|
||||||
/* readonly attribute unsigned long long unloadEventStart;
|
|
||||||
readonly attribute unsigned long long unloadEventEnd;
|
|
||||||
readonly attribute unsigned long long redirectStart;
|
|
||||||
readonly attribute unsigned long long redirectEnd;
|
|
||||||
readonly attribute unsigned long long fetchStart;
|
|
||||||
readonly attribute unsigned long long domainLookupStart;
|
|
||||||
readonly attribute unsigned long long domainLookupEnd;
|
|
||||||
readonly attribute unsigned long long connectStart;
|
|
||||||
readonly attribute unsigned long long connectEnd;
|
|
||||||
readonly attribute unsigned long long secureConnectionStart;
|
|
||||||
readonly attribute unsigned long long requestStart;
|
|
||||||
readonly attribute unsigned long long responseStart;
|
|
||||||
readonly attribute unsigned long long responseEnd; */
|
|
||||||
readonly attribute unsigned long long domLoading;
|
|
||||||
readonly attribute unsigned long long domInteractive;
|
|
||||||
readonly attribute unsigned long long domContentLoadedEventStart;
|
|
||||||
readonly attribute unsigned long long domContentLoadedEventEnd;
|
|
||||||
readonly attribute unsigned long long domComplete;
|
|
||||||
readonly attribute unsigned long long loadEventStart;
|
|
||||||
readonly attribute unsigned long long loadEventEnd;
|
|
||||||
/* Servo-onnly attribute for measuring when the top-level document (not iframes) is complete. */
|
|
||||||
[Pref="dom.testperf.enabled"]
|
|
||||||
readonly attribute unsigned long long topLevelDomComplete;
|
|
||||||
};
|
|
|
@ -812,11 +812,7 @@ impl WindowMethods for Window {
|
||||||
fn Performance(&self) -> DomRoot<Performance> {
|
fn Performance(&self) -> DomRoot<Performance> {
|
||||||
self.performance.or_init(|| {
|
self.performance.or_init(|| {
|
||||||
let global_scope = self.upcast::<GlobalScope>();
|
let global_scope = self.upcast::<GlobalScope>();
|
||||||
Performance::new(
|
Performance::new(global_scope, self.navigation_start_precise.get())
|
||||||
global_scope,
|
|
||||||
self.navigation_start.get(),
|
|
||||||
self.navigation_start_precise.get(),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -357,11 +357,7 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
|
||||||
fn Performance(&self) -> DomRoot<Performance> {
|
fn Performance(&self) -> DomRoot<Performance> {
|
||||||
self.performance.or_init(|| {
|
self.performance.or_init(|| {
|
||||||
let global_scope = self.upcast::<GlobalScope>();
|
let global_scope = self.upcast::<GlobalScope>();
|
||||||
Performance::new(
|
Performance::new(global_scope, self.navigation_start_precise)
|
||||||
global_scope,
|
|
||||||
0, /* navigation start is not used in workers */
|
|
||||||
self.navigation_start_precise,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::headers::is_forbidden_header_name;
|
use crate::dom::headers::is_forbidden_header_name;
|
||||||
use crate::dom::htmlformelement::{encode_multipart_form_data, generate_boundary};
|
use crate::dom::htmlformelement::{encode_multipart_form_data, generate_boundary};
|
||||||
use crate::dom::node::Node;
|
use crate::dom::node::Node;
|
||||||
|
use crate::dom::performanceresourcetiming::InitiatorType;
|
||||||
use crate::dom::progressevent::ProgressEvent;
|
use crate::dom::progressevent::ProgressEvent;
|
||||||
use crate::dom::servoparser::ServoParser;
|
use crate::dom::servoparser::ServoParser;
|
||||||
use crate::dom::urlsearchparams::URLSearchParams;
|
use crate::dom::urlsearchparams::URLSearchParams;
|
||||||
|
@ -36,7 +37,7 @@ use crate::dom::workerglobalscope::WorkerGlobalScope;
|
||||||
use crate::dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget;
|
use crate::dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget;
|
||||||
use crate::dom::xmlhttprequestupload::XMLHttpRequestUpload;
|
use crate::dom::xmlhttprequestupload::XMLHttpRequestUpload;
|
||||||
use crate::fetch::FetchCanceller;
|
use crate::fetch::FetchCanceller;
|
||||||
use crate::network_listener::{NetworkListener, PreInvoke};
|
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||||
use crate::task_source::networking::NetworkingTaskSource;
|
use crate::task_source::networking::NetworkingTaskSource;
|
||||||
use crate::task_source::TaskSourceName;
|
use crate::task_source::TaskSourceName;
|
||||||
use crate::timers::{OneshotTimerCallback, OneshotTimerHandle};
|
use crate::timers::{OneshotTimerCallback, OneshotTimerHandle};
|
||||||
|
@ -63,6 +64,7 @@ use net_traits::trim_http_whitespace;
|
||||||
use net_traits::CoreResourceMsg::Fetch;
|
use net_traits::CoreResourceMsg::Fetch;
|
||||||
use net_traits::{FetchChannels, FetchMetadata, FilteredMetadata};
|
use net_traits::{FetchChannels, FetchMetadata, FilteredMetadata};
|
||||||
use net_traits::{FetchResponseListener, NetworkError, ReferrerPolicy};
|
use net_traits::{FetchResponseListener, NetworkError, ReferrerPolicy};
|
||||||
|
use net_traits::{ResourceFetchTiming, ResourceTimingType};
|
||||||
use script_traits::DocumentActivity;
|
use script_traits::DocumentActivity;
|
||||||
use servo_atoms::Atom;
|
use servo_atoms::Atom;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
|
@ -95,6 +97,7 @@ struct XHRContext {
|
||||||
gen_id: GenerationId,
|
gen_id: GenerationId,
|
||||||
buf: DomRefCell<Vec<u8>>,
|
buf: DomRefCell<Vec<u8>>,
|
||||||
sync_status: DomRefCell<Option<ErrorResult>>,
|
sync_status: DomRefCell<Option<ErrorResult>>,
|
||||||
|
resource_timing: ResourceFetchTiming,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -257,13 +260,41 @@ impl XMLHttpRequest {
|
||||||
.process_data_available(self.gen_id, self.buf.borrow().clone());
|
.process_data_available(self.gen_id, self.buf.borrow().clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
|
fn process_response_eof(
|
||||||
|
&mut self,
|
||||||
|
response: Result<ResourceFetchTiming, NetworkError>,
|
||||||
|
) {
|
||||||
let rv = self
|
let rv = self
|
||||||
.xhr
|
.xhr
|
||||||
.root()
|
.root()
|
||||||
.process_response_complete(self.gen_id, response);
|
.process_response_complete(self.gen_id, response.map(|_| ()));
|
||||||
*self.sync_status.borrow_mut() = Some(rv);
|
*self.sync_status.borrow_mut() = Some(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming {
|
||||||
|
&mut self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing(&self) -> &ResourceFetchTiming {
|
||||||
|
&self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn submit_resource_timing(&mut self) {
|
||||||
|
network_listener::submit_timing(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceTimingListener for XHRContext {
|
||||||
|
fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
|
||||||
|
(
|
||||||
|
InitiatorType::XMLHttpRequest,
|
||||||
|
self.resource_timing_global().get_url().clone(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing_global(&self) -> DomRoot<GlobalScope> {
|
||||||
|
self.xhr.root().global()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreInvoke for XHRContext {
|
impl PreInvoke for XHRContext {
|
||||||
|
@ -1424,6 +1455,7 @@ impl XMLHttpRequest {
|
||||||
gen_id: self.generation_id.get(),
|
gen_id: self.generation_id.get(),
|
||||||
buf: DomRefCell::new(vec![]),
|
buf: DomRefCell::new(vec![]),
|
||||||
sync_status: DomRefCell::new(None),
|
sync_status: DomRefCell::new(None),
|
||||||
|
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let (task_source, script_port) = if self.sync.get() {
|
let (task_source, script_port) = if self.sync.get() {
|
||||||
|
|
|
@ -14,11 +14,12 @@ use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::bindings::trace::RootedTraceableBox;
|
use crate::dom::bindings::trace::RootedTraceableBox;
|
||||||
use crate::dom::globalscope::GlobalScope;
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::headers::Guard;
|
use crate::dom::headers::Guard;
|
||||||
|
use crate::dom::performanceresourcetiming::InitiatorType;
|
||||||
use crate::dom::promise::Promise;
|
use crate::dom::promise::Promise;
|
||||||
use crate::dom::request::Request;
|
use crate::dom::request::Request;
|
||||||
use crate::dom::response::Response;
|
use crate::dom::response::Response;
|
||||||
use crate::dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
|
use crate::dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
|
||||||
use crate::network_listener::{NetworkListener, PreInvoke};
|
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||||
use crate::task_source::TaskSourceName;
|
use crate::task_source::TaskSourceName;
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
|
@ -28,6 +29,7 @@ use net_traits::request::{Request as NetTraitsRequest, ServiceWorkersMode};
|
||||||
use net_traits::CoreResourceMsg::Fetch as NetTraitsFetch;
|
use net_traits::CoreResourceMsg::Fetch as NetTraitsFetch;
|
||||||
use net_traits::{FetchChannels, FetchResponseListener, NetworkError};
|
use net_traits::{FetchChannels, FetchResponseListener, NetworkError};
|
||||||
use net_traits::{FetchMetadata, FilteredMetadata, Metadata};
|
use net_traits::{FetchMetadata, FilteredMetadata, Metadata};
|
||||||
|
use net_traits::{ResourceFetchTiming, ResourceTimingType};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -37,6 +39,7 @@ struct FetchContext {
|
||||||
fetch_promise: Option<TrustedPromise>,
|
fetch_promise: Option<TrustedPromise>,
|
||||||
response_object: Trusted<Response>,
|
response_object: Trusted<Response>,
|
||||||
body: Vec<u8>,
|
body: Vec<u8>,
|
||||||
|
resource_timing: ResourceFetchTiming,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RAII fetch canceller object. By default initialized to not having a canceller
|
/// RAII fetch canceller object. By default initialized to not having a canceller
|
||||||
|
@ -143,6 +146,8 @@ pub fn Fetch(
|
||||||
},
|
},
|
||||||
Ok(r) => r.get_request(),
|
Ok(r) => r.get_request(),
|
||||||
};
|
};
|
||||||
|
let timing_type = request.timing_type();
|
||||||
|
|
||||||
let mut request_init = request_init_from_request(request);
|
let mut request_init = request_init_from_request(request);
|
||||||
|
|
||||||
// Step 3
|
// Step 3
|
||||||
|
@ -159,6 +164,7 @@ pub fn Fetch(
|
||||||
fetch_promise: Some(TrustedPromise::new(promise.clone())),
|
fetch_promise: Some(TrustedPromise::new(promise.clone())),
|
||||||
response_object: Trusted::new(&*response),
|
response_object: Trusted::new(&*response),
|
||||||
body: vec![],
|
body: vec![],
|
||||||
|
resource_timing: ResourceFetchTiming::new(timing_type),
|
||||||
}));
|
}));
|
||||||
let listener = NetworkListener {
|
let listener = NetworkListener {
|
||||||
context: fetch_context,
|
context: fetch_context,
|
||||||
|
@ -250,7 +256,7 @@ impl FetchResponseListener for FetchContext {
|
||||||
self.body.append(&mut chunk);
|
self.body.append(&mut chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_response_eof(&mut self, _response: Result<(), NetworkError>) {
|
fn process_response_eof(&mut self, _response: Result<ResourceFetchTiming, NetworkError>) {
|
||||||
let response = self.response_object.root();
|
let response = self.response_object.root();
|
||||||
let global = response.global();
|
let global = response.global();
|
||||||
let cx = global.get_cx();
|
let cx = global.get_cx();
|
||||||
|
@ -259,6 +265,35 @@ impl FetchResponseListener for FetchContext {
|
||||||
// TODO
|
// TODO
|
||||||
// ... trailerObject is not supported in Servo yet.
|
// ... trailerObject is not supported in Servo yet.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming {
|
||||||
|
&mut self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing(&self) -> &ResourceFetchTiming {
|
||||||
|
&self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn submit_resource_timing(&mut self) {
|
||||||
|
// navigation submission is handled in servoparser/mod.rs
|
||||||
|
match self.resource_timing.timing_type {
|
||||||
|
ResourceTimingType::Resource => network_listener::submit_timing(self),
|
||||||
|
_ => {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceTimingListener for FetchContext {
|
||||||
|
fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
|
||||||
|
(
|
||||||
|
InitiatorType::Fetch,
|
||||||
|
self.resource_timing_global().get_url().clone(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing_global(&self) -> DomRoot<GlobalScope> {
|
||||||
|
self.response_object.root().global()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_headers_with_metadata(r: DomRoot<Response>, m: Metadata) {
|
fn fill_headers_with_metadata(r: DomRoot<Response>, m: Metadata) {
|
||||||
|
|
|
@ -7,20 +7,28 @@
|
||||||
//! no guarantee that the responsible nodes will still exist in the future if the
|
//! no guarantee that the responsible nodes will still exist in the future if the
|
||||||
//! layout thread holds on to them during asynchronous operations.
|
//! layout thread holds on to them during asynchronous operations.
|
||||||
|
|
||||||
|
use crate::dom::bindings::refcounted::Trusted;
|
||||||
use crate::dom::bindings::reflector::DomObject;
|
use crate::dom::bindings::reflector::DomObject;
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::document::Document;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::node::{document_from_node, Node};
|
use crate::dom::node::{document_from_node, Node};
|
||||||
use crate::network_listener::{NetworkListener, PreInvoke};
|
use crate::dom::performanceresourcetiming::InitiatorType;
|
||||||
|
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use net_traits::image_cache::{ImageCache, PendingImageId};
|
use net_traits::image_cache::{ImageCache, PendingImageId};
|
||||||
use net_traits::request::{Destination, RequestInit as FetchRequestInit};
|
use net_traits::request::{Destination, RequestInit as FetchRequestInit};
|
||||||
use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError};
|
use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError};
|
||||||
|
use net_traits::{ResourceFetchTiming, ResourceTimingType};
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
struct LayoutImageContext {
|
struct LayoutImageContext {
|
||||||
id: PendingImageId,
|
id: PendingImageId,
|
||||||
cache: Arc<dyn ImageCache>,
|
cache: Arc<dyn ImageCache>,
|
||||||
|
resource_timing: ResourceFetchTiming,
|
||||||
|
doc: Trusted<Document>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FetchResponseListener for LayoutImageContext {
|
impl FetchResponseListener for LayoutImageContext {
|
||||||
|
@ -36,10 +44,35 @@ impl FetchResponseListener for LayoutImageContext {
|
||||||
.notify_pending_response(self.id, FetchResponseMsg::ProcessResponseChunk(payload));
|
.notify_pending_response(self.id, FetchResponseMsg::ProcessResponseChunk(payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
|
fn process_response_eof(&mut self, response: Result<ResourceFetchTiming, NetworkError>) {
|
||||||
self.cache
|
self.cache
|
||||||
.notify_pending_response(self.id, FetchResponseMsg::ProcessResponseEOF(response));
|
.notify_pending_response(self.id, FetchResponseMsg::ProcessResponseEOF(response));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming {
|
||||||
|
&mut self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing(&self) -> &ResourceFetchTiming {
|
||||||
|
&self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn submit_resource_timing(&mut self) {
|
||||||
|
network_listener::submit_timing(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceTimingListener for LayoutImageContext {
|
||||||
|
fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
|
||||||
|
(
|
||||||
|
InitiatorType::Other,
|
||||||
|
self.resource_timing_global().get_url().clone(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing_global(&self) -> DomRoot<GlobalScope> {
|
||||||
|
self.doc.root().global()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreInvoke for LayoutImageContext {}
|
impl PreInvoke for LayoutImageContext {}
|
||||||
|
@ -50,9 +83,13 @@ pub fn fetch_image_for_layout(
|
||||||
id: PendingImageId,
|
id: PendingImageId,
|
||||||
cache: Arc<dyn ImageCache>,
|
cache: Arc<dyn ImageCache>,
|
||||||
) {
|
) {
|
||||||
|
let document = document_from_node(node);
|
||||||
|
|
||||||
let context = Arc::new(Mutex::new(LayoutImageContext {
|
let context = Arc::new(Mutex::new(LayoutImageContext {
|
||||||
id: id,
|
id: id,
|
||||||
cache: cache,
|
cache: cache,
|
||||||
|
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
|
||||||
|
doc: Trusted::new(&document),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let document = document_from_node(node);
|
let document = document_from_node(node);
|
||||||
|
|
|
@ -2,10 +2,16 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
|
use crate::dom::performanceentry::PerformanceEntry;
|
||||||
|
use crate::dom::performanceresourcetiming::{InitiatorType, PerformanceResourceTiming};
|
||||||
use crate::task::{TaskCanceller, TaskOnce};
|
use crate::task::{TaskCanceller, TaskOnce};
|
||||||
use crate::task_source::networking::NetworkingTaskSource;
|
use crate::task_source::networking::NetworkingTaskSource;
|
||||||
use crate::task_source::TaskSource;
|
use crate::task_source::TaskSource;
|
||||||
use net_traits::{Action, FetchResponseListener, FetchResponseMsg};
|
use net_traits::{Action, FetchResponseListener, FetchResponseMsg, ResourceTimingType};
|
||||||
|
use servo_url::ServoUrl;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
/// An off-thread sink for async network event tasks. All such events are forwarded to
|
/// An off-thread sink for async network event tasks. All such events are forwarded to
|
||||||
|
@ -16,6 +22,39 @@ pub struct NetworkListener<Listener: PreInvoke + Send + 'static> {
|
||||||
pub canceller: Option<TaskCanceller>,
|
pub canceller: Option<TaskCanceller>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ResourceTimingListener {
|
||||||
|
fn resource_timing_information(&self) -> (InitiatorType, ServoUrl);
|
||||||
|
fn resource_timing_global(&self) -> DomRoot<GlobalScope>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn submit_timing<T: ResourceTimingListener + FetchResponseListener>(listener: &T) {
|
||||||
|
if listener.resource_timing().timing_type != ResourceTimingType::Resource {
|
||||||
|
warn!(
|
||||||
|
"Submitting non-resource ({:?}) timing as resource",
|
||||||
|
listener.resource_timing().timing_type
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (initiator_type, url) = listener.resource_timing_information();
|
||||||
|
if initiator_type == InitiatorType::Other {
|
||||||
|
warn!("Ignoring InitiatorType::Other resource {:?}", url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let global = listener.resource_timing_global();
|
||||||
|
let performance_entry = PerformanceResourceTiming::new(
|
||||||
|
&global,
|
||||||
|
url,
|
||||||
|
initiator_type,
|
||||||
|
None,
|
||||||
|
&listener.resource_timing(),
|
||||||
|
);
|
||||||
|
global
|
||||||
|
.performance()
|
||||||
|
.queue_entry(performance_entry.upcast::<PerformanceEntry>(), false);
|
||||||
|
}
|
||||||
|
|
||||||
impl<Listener: PreInvoke + Send + 'static> NetworkListener<Listener> {
|
impl<Listener: PreInvoke + Send + 'static> NetworkListener<Listener> {
|
||||||
pub fn notify<A: Action<Listener> + Send + 'static>(&self, action: A) {
|
pub fn notify<A: Action<Listener> + Send + 'static>(&self, action: A) {
|
||||||
let task = ListenerTask {
|
let task = ListenerTask {
|
||||||
|
|
|
@ -107,7 +107,10 @@ use net_traits::image_cache::{ImageCache, PendingImageResponse};
|
||||||
use net_traits::request::{CredentialsMode, Destination, RedirectMode, RequestInit};
|
use net_traits::request::{CredentialsMode, Destination, RedirectMode, RequestInit};
|
||||||
use net_traits::storage_thread::StorageType;
|
use net_traits::storage_thread::StorageType;
|
||||||
use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg};
|
use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg};
|
||||||
use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceThreads};
|
use net_traits::{
|
||||||
|
Metadata, NetworkError, ReferrerPolicy, ResourceFetchTiming, ResourceThreads,
|
||||||
|
ResourceTimingType,
|
||||||
|
};
|
||||||
use profile_traits::mem::{self as profile_mem, OpaqueSender, ReportsChan};
|
use profile_traits::mem::{self as profile_mem, OpaqueSender, ReportsChan};
|
||||||
use profile_traits::time::{self as profile_time, profile, ProfilerCategory};
|
use profile_traits::time::{self as profile_time, profile, ProfilerCategory};
|
||||||
use script_layout_interface::message::{self, Msg, NewLayoutThreadInfo, ReflowGoal};
|
use script_layout_interface::message::{self, Msg, NewLayoutThreadInfo, ReflowGoal};
|
||||||
|
@ -3097,9 +3100,12 @@ impl ScriptThread {
|
||||||
fetch_metadata: Result<FetchMetadata, NetworkError>,
|
fetch_metadata: Result<FetchMetadata, NetworkError>,
|
||||||
) {
|
) {
|
||||||
match fetch_metadata {
|
match fetch_metadata {
|
||||||
Ok(_) => {},
|
Ok(_) => (),
|
||||||
Err(ref e) => warn!("Network error: {:?}", e),
|
Err(ref e) => {
|
||||||
|
warn!("Network error: {:?}", e);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut incomplete_parser_contexts = self.incomplete_parser_contexts.borrow_mut();
|
let mut incomplete_parser_contexts = self.incomplete_parser_contexts.borrow_mut();
|
||||||
let parser = incomplete_parser_contexts
|
let parser = incomplete_parser_contexts
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
|
@ -3119,12 +3125,13 @@ impl ScriptThread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_fetch_eof(&self, id: PipelineId, eof: Result<(), NetworkError>) {
|
fn handle_fetch_eof(&self, id: PipelineId, eof: Result<ResourceFetchTiming, NetworkError>) {
|
||||||
let idx = self
|
let idx = self
|
||||||
.incomplete_parser_contexts
|
.incomplete_parser_contexts
|
||||||
.borrow()
|
.borrow()
|
||||||
.iter()
|
.iter()
|
||||||
.position(|&(pipeline_id, _)| pipeline_id == id);
|
.position(|&(pipeline_id, _)| pipeline_id == id);
|
||||||
|
|
||||||
if let Some(idx) = idx {
|
if let Some(idx) = idx {
|
||||||
let (_, mut ctxt) = self.incomplete_parser_contexts.borrow_mut().remove(idx);
|
let (_, mut ctxt) = self.incomplete_parser_contexts.borrow_mut().remove(idx);
|
||||||
ctxt.process_response_eof(eof);
|
ctxt.process_response_eof(eof);
|
||||||
|
@ -3161,7 +3168,7 @@ impl ScriptThread {
|
||||||
|
|
||||||
context.process_response(Ok(FetchMetadata::Unfiltered(meta)));
|
context.process_response(Ok(FetchMetadata::Unfiltered(meta)));
|
||||||
context.process_response_chunk(chunk);
|
context.process_response_chunk(chunk);
|
||||||
context.process_response_eof(Ok(()));
|
context.process_response_eof(Ok(ResourceFetchTiming::new(ResourceTimingType::None)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_css_error_reporting(
|
fn handle_css_error_reporting(
|
||||||
|
|
|
@ -6,13 +6,16 @@ use crate::document_loader::LoadType;
|
||||||
use crate::dom::bindings::inheritance::Castable;
|
use crate::dom::bindings::inheritance::Castable;
|
||||||
use crate::dom::bindings::refcounted::Trusted;
|
use crate::dom::bindings::refcounted::Trusted;
|
||||||
use crate::dom::bindings::reflector::DomObject;
|
use crate::dom::bindings::reflector::DomObject;
|
||||||
|
use crate::dom::bindings::root::DomRoot;
|
||||||
use crate::dom::document::Document;
|
use crate::dom::document::Document;
|
||||||
use crate::dom::element::Element;
|
use crate::dom::element::Element;
|
||||||
use crate::dom::eventtarget::EventTarget;
|
use crate::dom::eventtarget::EventTarget;
|
||||||
|
use crate::dom::globalscope::GlobalScope;
|
||||||
use crate::dom::htmlelement::HTMLElement;
|
use crate::dom::htmlelement::HTMLElement;
|
||||||
use crate::dom::htmllinkelement::{HTMLLinkElement, RequestGenerationId};
|
use crate::dom::htmllinkelement::{HTMLLinkElement, RequestGenerationId};
|
||||||
use crate::dom::node::{document_from_node, window_from_node};
|
use crate::dom::node::{document_from_node, window_from_node};
|
||||||
use crate::network_listener::{NetworkListener, PreInvoke};
|
use crate::dom::performanceresourcetiming::InitiatorType;
|
||||||
|
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||||
use cssparser::SourceLocation;
|
use cssparser::SourceLocation;
|
||||||
use encoding_rs::UTF_8;
|
use encoding_rs::UTF_8;
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
|
@ -22,6 +25,7 @@ use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestIni
|
||||||
use net_traits::{
|
use net_traits::{
|
||||||
FetchMetadata, FetchResponseListener, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy,
|
FetchMetadata, FetchResponseListener, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy,
|
||||||
};
|
};
|
||||||
|
use net_traits::{ResourceFetchTiming, ResourceTimingType};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
|
@ -79,6 +83,7 @@ pub struct StylesheetContext {
|
||||||
/// A token which must match the generation id of the `HTMLLinkElement` for it to load the stylesheet.
|
/// A token which must match the generation id of the `HTMLLinkElement` for it to load the stylesheet.
|
||||||
/// This is ignored for `HTMLStyleElement` and imports.
|
/// This is ignored for `HTMLStyleElement` and imports.
|
||||||
request_generation_id: Option<RequestGenerationId>,
|
request_generation_id: Option<RequestGenerationId>,
|
||||||
|
resource_timing: ResourceFetchTiming,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreInvoke for StylesheetContext {}
|
impl PreInvoke for StylesheetContext {}
|
||||||
|
@ -108,7 +113,7 @@ impl FetchResponseListener for StylesheetContext {
|
||||||
self.data.append(&mut payload);
|
self.data.append(&mut payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_response_eof(&mut self, status: Result<(), NetworkError>) {
|
fn process_response_eof(&mut self, status: Result<ResourceFetchTiming, NetworkError>) {
|
||||||
let elem = self.elem.root();
|
let elem = self.elem.root();
|
||||||
let document = self.document.root();
|
let document = self.document.root();
|
||||||
let mut successful = false;
|
let mut successful = false;
|
||||||
|
@ -207,6 +212,35 @@ impl FetchResponseListener for StylesheetContext {
|
||||||
elem.upcast::<EventTarget>().fire_event(event);
|
elem.upcast::<EventTarget>().fire_event(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming {
|
||||||
|
&mut self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing(&self) -> &ResourceFetchTiming {
|
||||||
|
&self.resource_timing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn submit_resource_timing(&mut self) {
|
||||||
|
network_listener::submit_timing(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceTimingListener for StylesheetContext {
|
||||||
|
fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
|
||||||
|
let initiator_type = InitiatorType::LocalName(
|
||||||
|
self.elem
|
||||||
|
.root()
|
||||||
|
.upcast::<Element>()
|
||||||
|
.local_name()
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
(initiator_type, self.url.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resource_timing_global(&self) -> DomRoot<GlobalScope> {
|
||||||
|
document_from_node(&*self.elem.root()).global()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StylesheetLoader<'a> {
|
pub struct StylesheetLoader<'a> {
|
||||||
|
@ -241,6 +275,7 @@ impl<'a> StylesheetLoader<'a> {
|
||||||
document: Trusted::new(&*document),
|
document: Trusted::new(&*document),
|
||||||
origin_clean: true,
|
origin_clean: true,
|
||||||
request_generation_id: gen,
|
request_generation_id: gen,
|
||||||
|
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||||
|
|
|
@ -103,6 +103,8 @@ skip: true
|
||||||
skip: false
|
skip: false
|
||||||
[referrer-policy]
|
[referrer-policy]
|
||||||
skip: false
|
skip: false
|
||||||
|
[resource-timing]
|
||||||
|
skip: false
|
||||||
[subresource-integrity]
|
[subresource-integrity]
|
||||||
skip: false
|
skip: false
|
||||||
[touch-events]
|
[touch-events]
|
||||||
|
|
|
@ -7,3 +7,4 @@
|
||||||
|
|
||||||
[Microtasks evaluate afterward when the stack is not empty using createElement()]
|
[Microtasks evaluate afterward when the stack is not empty using createElement()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -24,5 +24,3 @@
|
||||||
[A Keep-Alive fetch() with a body over the Quota Limit should reject.]
|
[A Keep-Alive fetch() with a body over the Quota Limit should reject.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
||||||
[request-keepalive-quota.html?include=slow-1]
|
|
||||||
|
|
|
@ -2,31 +2,21 @@
|
||||||
[idlharness]
|
[idlharness]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Performance interface: existence and properties of interface object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Performance interface: existence and properties of interface prototype object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Performance interface: attribute timeOrigin]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Performance interface: operation toJSON()]
|
[Performance interface: operation toJSON()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Performance interface: performance must inherit property "timeOrigin" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Performance interface: performance must inherit property "toJSON()" with the proper type]
|
[Performance interface: performance must inherit property "toJSON()" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Test default toJSON operation of Performance]
|
[Test default toJSON operation of Performance]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
||||||
[idlharness.any.serviceworker.html]
|
[idlharness.any.serviceworker.html]
|
||||||
[idlharness]
|
[idlharness]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
||||||
[idlharness.any.sharedworker.html]
|
[idlharness.any.sharedworker.html]
|
||||||
[idlharness]
|
[idlharness]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
@ -42,21 +32,9 @@
|
||||||
[idlharness]
|
[idlharness]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Performance interface: existence and properties of interface object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Performance interface: existence and properties of interface prototype object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Performance interface: attribute timeOrigin]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Performance interface: operation toJSON()]
|
[Performance interface: operation toJSON()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Performance interface: performance must inherit property "timeOrigin" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Performance interface: performance must inherit property "toJSON()" with the proper type]
|
[Performance interface: performance must inherit property "toJSON()" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[test_cross_frame_start.html]
|
||||||
|
[Child created at least 1 second after parent]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Child and parent time bases are correct]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -6,6 +6,3 @@
|
||||||
[Window and worker timeOrigins are close when created one after another.]
|
[Window and worker timeOrigins are close when created one after another.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Window and worker timeOrigins differ when worker is created after a delay.]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[window-worker-timeOrigin.window.html]
|
|
||||||
type: testharness
|
|
||||||
[timeOrigin and now() should be correctly ordered between window and worker]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -292,7 +292,3 @@
|
||||||
[<meta>: "1\\furl=foo"]
|
[<meta>: "1\\furl=foo"]
|
||||||
expected: TIMEOUT
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
|
||||||
[parsing.html?131-last]
|
|
||||||
|
|
||||||
[parsing.html?81-90]
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
[dom_interactive_image_document.html]
|
||||||
|
expected: ERROR
|
||||||
|
[Test domInteractive on image document]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
[dom_interactive_media_document.html]
|
||||||
|
expected: ERROR
|
||||||
|
[Test domInteractive on media document]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
|
@ -1,56 +1,11 @@
|
||||||
[nav2_idlharness.html]
|
[nav2_idlharness.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
[PerformanceNavigationTiming interface: existence and properties of interface object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface object length]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface object name]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface: existence and properties of interface prototype object]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface: existence and properties of interface prototype object's "constructor" property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface: attribute unloadEventStart]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface: attribute unloadEventEnd]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface: attribute domInteractive]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface: attribute domContentLoadedEventStart]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface: attribute domContentLoadedEventEnd]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface: attribute domComplete]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface: attribute loadEventStart]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface: attribute loadEventEnd]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface: attribute type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface: attribute redirectCount]
|
[PerformanceNavigationTiming interface: attribute redirectCount]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface: operation toJSON()]
|
[PerformanceNavigationTiming interface: operation toJSON()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[PerformanceNavigationTiming interface: existence and properties of interface prototype object's @@unscopables property]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Navigation Timing 2 IDL tests]
|
[Navigation Timing 2 IDL tests]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[nav2_test_attributes_exist.html]
|
[nav2_test_attributes_exist.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
|
expected: TIMEOUT
|
||||||
[Performance navigation timing entries are observable.]
|
[Performance navigation timing entries are observable.]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[nav2_test_attributes_values.html]
|
[nav2_test_attributes_values.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
|
expected: TIMEOUT
|
||||||
[Performance navigation timing instance's value is reasonable.]
|
[Performance navigation timing instance's value is reasonable.]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[nav2_test_instance_accessors.html]
|
[nav2_test_instance_accessors.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
|
expected: TIMEOUT
|
||||||
[Performance navigation timing entries are accessible through three different accessors.]
|
[Performance navigation timing entries are accessible through three different accessors.]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[nav2_test_navigation_type_navigate.html]
|
[nav2_test_navigation_type_navigate.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
|
expected: TIMEOUT
|
||||||
[Navigation type to be navigate.]
|
[Navigation type to be navigate.]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[nav2_test_redirect_none.html]
|
[nav2_test_redirect_none.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
|
expected: TIMEOUT
|
||||||
[Naivation without redirects.]
|
[Naivation without redirects.]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[nav2_test_unique_nav_instances.html]
|
[nav2_test_unique_nav_instances.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
|
expected: TIMEOUT
|
||||||
[Each window has a unique nav timing 2 instance.]
|
[Each window has a unique nav timing 2 instance.]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
[po-navigation.html]
|
[po-navigation.html]
|
||||||
|
expected: TIMEOUT
|
||||||
[navigation entry is observable]
|
[navigation entry is observable]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
|
|
@ -36,3 +36,27 @@
|
||||||
[window.performance.timing.unloadEventStart is defined.]
|
[window.performance.timing.unloadEventStart is defined.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[window.performance.timing.domComplete is defined.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[window.performance.timing.domContentLoadedEventEnd is defined.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[window.performance.timing.domContentLoadedEventStart is defined.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[window.performance.timing.domInteractive is defined.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[window.performance.timing.domLoading is defined.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[window.performance.timing.loadEventEnd is defined.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[window.performance.timing.loadEventStart is defined.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[window.performance.timing.navigationStart is defined.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,6 @@
|
||||||
|
|
||||||
[case-sensitivity.any.html]
|
[case-sensitivity.any.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
[getEntriesByType values are case sensitive]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[getEntriesByName values are case sensitive]
|
[getEntriesByName values are case sensitive]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
[clear_resource_timing_functionality.html]
|
||||||
|
expected: ERROR
|
||||||
|
[4 resource timing entries should be stored in this page.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[No resource timing entries should be stored after clearResourceTimings.]
|
||||||
|
expected: FAIL
|
||||||
|
|
243
tests/wpt/metadata/resource-timing/idlharness.any.js.ini
Normal file
243
tests/wpt/metadata/resource-timing/idlharness.any.js.ini
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
[idlharness.any.html]
|
||||||
|
[PerformanceResourceTiming interface: attribute transferSize]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "transferSize" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute decodedBodySize]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Stringification of resource]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Test default toJSON operation of PerformanceNavigationTiming]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "toJSON()" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "decodedBodySize" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute encodedBodySize]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "encodedBodySize" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: operation toJSON()]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming must be primary interface of resource]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "workerStart" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute responseEnd]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance interface: operation setResourceTimingBufferSize(unsigned long)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute secureConnectionStart]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance interface: calling setResourceTimingBufferSize(unsigned long) on performance with too few arguments must throw TypeError]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute fetchStart]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "secureConnectionStart" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "domainLookupStart" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "connectStart" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute workerStart]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute domainLookupStart]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "redirectStart" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute connectStart]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance interface: operation clearResourceTimings()]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "responseEnd" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance interface: performance must inherit property "onresourcetimingbufferfull" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance interface: performance must inherit property "setResourceTimingBufferSize(unsigned long)" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance interface: attribute onresourcetimingbufferfull]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute connectEnd]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "redirectEnd" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute redirectEnd]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "domainLookupEnd" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance interface: performance must inherit property "clearResourceTimings()" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute domainLookupEnd]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "fetchStart" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute redirectStart]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "connectEnd" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
||||||
|
[idlharness.any.worker.html]
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "workerStart" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "initiatorType" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute transferSize]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Test default toJSON operation of toJSON object]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "secureConnectionStart" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "requestStart" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "transferSize" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "domainLookupStart" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "connectStart" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute decodedBodySize]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Stringification of resource]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "redirectStart" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "toJSON()" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "responseEnd" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "redirectEnd" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "nextHopProtocol" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "domainLookupEnd" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "decodedBodySize" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "fetchStart" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute encodedBodySize]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "connectEnd" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "encodedBodySize" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: operation toJSON()]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: resource must inherit property "responseStart" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming must be primary interface of resource]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute responseEnd]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance interface: operation setResourceTimingBufferSize(unsigned long)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute secureConnectionStart]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance interface: calling setResourceTimingBufferSize(unsigned long) on performance with too few arguments must throw TypeError]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute fetchStart]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute workerStart]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute domainLookupStart]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute connectStart]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance interface: operation clearResourceTimings()]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance interface: performance must inherit property "onresourcetimingbufferfull" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance interface: performance must inherit property "setResourceTimingBufferSize(unsigned long)" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance interface: attribute onresourcetimingbufferfull]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute connectEnd]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute redirectEnd]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance interface: performance must inherit property "clearResourceTimings()" with the proper type]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute domainLookupEnd]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceResourceTiming interface: attribute redirectStart]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[resource-timing-tojson.html]
|
||||||
|
[Untitled]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Test toJSON() in PerformanceResourceTiming]
|
||||||
|
expected: FAIL
|
||||||
|
|
55
tests/wpt/metadata/resource-timing/resource-timing.html.ini
Normal file
55
tests/wpt/metadata/resource-timing/resource-timing.html.ini
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
[resource-timing.html]
|
||||||
|
[No timeline entry for about:blank]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Setting 'document.domain' does not effect same-origin checks]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['iframe: 250ms delay before 'responseStart', another 250ms delay before 'responseEnd'.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['xmlhttprequest: 250ms delay before 'responseStart', another 250ms delay before 'responseEnd'.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['script: 250ms delay before 'responseStart', another 250ms delay before 'responseEnd'.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['link: 250ms delay before 'responseStart', another 250ms delay before 'responseEnd'.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['iframe (Redirected): 250ms delay before 'redirectEnd', another 250ms delay before 'responseStart'.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['xmlhttprequest (Redirected): 250ms delay before 'redirectEnd', another 250ms delay before 'responseStart'.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['script (Redirected): 250ms delay before 'redirectEnd', another 250ms delay before 'responseStart'.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['link (Redirected): 250ms delay before 'redirectEnd', another 250ms delay before 'responseStart'.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['iframe (Populate cache): The initial request populates the cache (if appropriate).]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['iframe (Potentially Cached): Immediately fetch the same URL, exercising the cache hit path (if any).]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['xmlhttprequest (Populate cache): The initial request populates the cache (if appropriate).]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['xmlhttprequest (Potentially Cached): Immediately fetch the same URL, exercising the cache hit path (if any).]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['script (Populate cache): The initial request populates the cache (if appropriate).]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['script (Potentially Cached): Immediately fetch the same URL, exercising the cache hit path (if any).]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['link (Populate cache): The initial request populates the cache (if appropriate).]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
['link (Potentially Cached): Immediately fetch the same URL, exercising the cache hit path (if any).]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
[resource_TAO_cross_origin_redirect_chain.html]
|
||||||
|
expected: ERROR
|
||||||
|
[There should be one entry.]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[resource_TAO_null.htm]
|
||||||
|
[redirectStart, redirectEnd, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, and responseStart -- should be all returned as 0 when the value of Timing-Allow-Origin is null and TAO algorithm fails]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
[resource_TAO_origin.htm]
|
||||||
|
[domainLookupStart should not be 0 in timing-allow cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[domainLookupEnd should not be 0 in timing-allow cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[connectStart should not be 0 in timing-allow cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[connectEnd should not be 0 in timing-allow cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[requestStart should not be 0 in timing-allow cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[responseStart should not be 0 in timing-allow cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[fetchStart should not be 0 in timing-allow cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[responseEnd should not be 0 in timing-allow cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[redirectStart should be 0 in cross-origin request since no redirect.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[redirectEnd should be 0 in cross-origin request since no redirect.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[secureConnectionStart should be 0 in cross-origin request since no ssl!]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[resource_TAO_origin_uppercase.htm]
|
||||||
|
[redirectStart, redirectEnd, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, and responseStart -- should be all returned as 0 when the value of Timing-Allow-Origin is NOT a case-sensitive match for the value of the origin of the current document and TAO algorithm passes]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[resource_TAO_space.htm]
|
||||||
|
[redirectStart, redirectEnd, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, and responseStart -- should be all returned as 0 when the Timing-Allow-Origin header value of the HTTP response is a space separated origin/wildcard list]
|
||||||
|
expected: FAIL
|
||||||
|
|
28
tests/wpt/metadata/resource-timing/resource_TAO_zero.htm.ini
Normal file
28
tests/wpt/metadata/resource-timing/resource_TAO_zero.htm.ini
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
[resource_TAO_zero.htm]
|
||||||
|
[fetchStart should be greater than 0 in cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[responseEnd should be greater than 0 in cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[secureConnectionStart should be 0 in cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[connectEnd should be 0 in cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[domainLookupStart should be 0 in cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[connectStart should be 0 in cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[redirectStart should be 0 in cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[domainLookupEnd should be 0 in cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[redirectEnd should be 0 in cross-origin request.]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[resource_cached.htm]
|
||||||
|
[There should be two entries]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[resource_connection_reuse.html]
|
||||||
|
[There should be 2 PerformanceEntries]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[resource_dedicated_worker.html]
|
||||||
|
[There should be six entries: 4 scripts, 1 stylesheet, and the worker itself]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
[resource_dynamic_insertion.html]
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/resource_timing_test0.css is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/resource_timing_test0.png is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/inject_resource_test.html is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/inject_resource_test.html is expected to have initiatorType iframe]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[resource_ignore_data_url.html]
|
||||||
|
[entries.length == 0]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[resource_ignore_failures.html]
|
||||||
|
[entries.length == 0]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[resource_initiator_types.html]
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/all_resource_types.htm is not expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/green_frame.htm is not expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
[resource_memory_cached.sub.html]
|
||||||
|
expected: ERROR
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/blue.png?id=cached is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[requestStart should be non-zero on the same-origin request]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Entry name should start with cross-origin domain]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Entry name should end with file name]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[responseEnd should not be before startTime]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/inject_resource_test.html is not expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
[resource_redirects.html]
|
||||||
|
[http://web-platform.test:8000/common/redirect.py?location=/resource-timing/resources/resource_timing_test0.css is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/common/redirect.py?location=/resource-timing/resources/blue.png is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/common/redirect.py?location=/resource-timing/resources/blank_page_green.htm is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/common/redirect.py?location=/resource-timing/resources/empty_script.js is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/common/redirect.py?location=/resource-timing/resources/blank_page_green.htm?id=xhr is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/inject_resource_test.html is not expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[resource_reparenting.html]
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/blue.png?id=move_to_child is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/inject_resource_test.html is not expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
[resource_script_types.html]
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/empty_script.js?id=1 is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/empty_script.js?id=2 is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/empty_script.js?id=3 is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/empty_script.js?id=4 is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/empty_script.js?id=5 is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/empty_script.js?id=6 is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/empty_script.js?id=7 is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/empty_script.js?id=8 is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/empty_script.js?id=9 is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/inject_resource_test.html is not expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
[resource_subframe_self_navigation.html]
|
||||||
|
[Subsequent <iframe> navigations don't appear in the resource-timing buffer.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Subsequent <frame> navigations don't appear in the resource-timing buffer.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Subsequent <embed> navigations don't appear in the resource-timing buffer.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Subsequent <object> navigations don't appear in the resource-timing buffer.]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[resource_timing.worker.html]
|
||||||
|
[Performance Resouce Entries in workers]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[resource_timing_TAO_cross_origin_redirect.html]
|
||||||
|
[This test validates the values in resource timing for a timing allowed cross-origin redirect.]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
[resource_timing_buffer_full_eventually.html]
|
||||||
|
expected: TIMEOUT
|
||||||
|
[Finite resource timing entries buffer size]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
[resource_timing_buffer_full_when_populate_entries.html]
|
||||||
|
[This test validates the functionality of onresourcetimingbufferfull in resource timing.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[There should only be |bufferSize| resource entries.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[onresourcetimingbufferfull should have been invoked once buffer is full.]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[resource_timing_buffer_full_when_shrink_buffer_size.html]
|
||||||
|
[This test validates the functionality of onresourcetimingbufferfull in resource timing.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[There are 4 scripts, and setResourceTimingBufferSize does not reduce the size.]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[resource_timing_cross_origin_redirect.html]
|
||||||
|
[This test validates the values in resource timing for a cross-origin redirect.]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
[resource_timing_cross_origin_redirect_chain.html]
|
||||||
|
expected: ERROR
|
||||||
|
[There should be one entry.]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[resource_timing_same_origin_redirect.html]
|
||||||
|
[This test validates the values of the redirectStart/End in resource timing for a same-origin resource redirect.]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
[resource_timing_store_and_clear_during_callback.html]
|
||||||
|
[This test validates the behavior of read and clear operation in onresourcetimingbufferfull callback of resource timing.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[No entry should be stored in resource timing buffer since its cleared once an item arrived.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[6 resource timing entries should be moved to global buffer.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resources/testharness.js is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resources/testharnessreport.js is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/webperftestharness.js is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/webperftestharnessextension.js is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/empty_script.js is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[http://web-platform.test:8000/resource-timing/resources/resource_timing_test0.js is expected to be in the Resource Timing buffer]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[single-entry-per-resource.html]
|
||||||
|
[One resource when reusing data]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Only one resource entry per resource]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
[test_resource_timing.html]
|
||||||
|
expected: TIMEOUT
|
||||||
|
[window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (iframe)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct name, initiatorType, startTime, and duration (iframe)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct order of timing attributes (iframe)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct network transfer attributes (iframe)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct protocol attribute (iframe)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (img)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct name, initiatorType, startTime, and duration (img)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct order of timing attributes (img)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct network transfer attributes (img)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct protocol attribute (img)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (link)]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
||||||
|
[PerformanceEntry has correct name, initiatorType, startTime, and duration (link)]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
||||||
|
[PerformanceEntry has correct order of timing attributes (link)]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
||||||
|
[PerformanceEntry has correct network transfer attributes (link)]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
||||||
|
[PerformanceEntry has correct protocol attribute (link)]
|
||||||
|
expected: NOTRUN
|
||||||
|
|
||||||
|
[window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (script)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct name, initiatorType, startTime, and duration (script)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct order of timing attributes (script)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct network transfer attributes (script)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct protocol attribute (script)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (xmlhttprequest)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct name, initiatorType, startTime, and duration (xmlhttprequest)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct order of timing attributes (xmlhttprequest)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct network transfer attributes (xmlhttprequest)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[PerformanceEntry has correct protocol attribute (xmlhttprequest)]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
[import-in-moduleworker.html]
|
|
||||||
[Base URL in module dedicated workers: import]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
[sharedworker-in-worker.html]
|
|
||||||
[Base URL in workers: new SharedWorker()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[005.html]
|
|
||||||
type: testharness
|
|
||||||
[dedicated worker in shared worker in dedicated worker]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,3 +1,26 @@
|
||||||
[worker-performance.worker.html]
|
[worker-performance.worker.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: CRASH
|
[Can use performance.getEntriesByType in workers]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Performance marks and measures seem to be working correctly in workers]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Can use clearMarks and clearMeasures in workers]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Resource timing seems to work in workers]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[performance.clearResourceTimings in workers]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[performance.setResourceTimingBufferSize in workers]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[performance.timing is not available in workers]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[performance.toJSON is available in workers]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,3 @@
|
||||||
[sync-no-timeout]
|
[sync-no-timeout]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
||||||
[sync-no-timeout.any.worker.html]
|
|
||||||
|
|
||||||
[sync-no-timeout.any.html]
|
|
||||||
|
|
|
@ -27064,7 +27064,7 @@
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"mozilla/interfaces.html": [
|
"mozilla/interfaces.html": [
|
||||||
"b1de57409ad5e6f9fedeb8a34c9474b4e378ec0a",
|
"ad17e930ddb5bc2daecb86216efe8885ae399173",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"mozilla/interfaces.js": [
|
"mozilla/interfaces.js": [
|
||||||
|
@ -27072,7 +27072,7 @@
|
||||||
"support"
|
"support"
|
||||||
],
|
],
|
||||||
"mozilla/interfaces.worker.js": [
|
"mozilla/interfaces.worker.js": [
|
||||||
"fbd6e92c097dea4f99924de219c9f6aa07a45282",
|
"a5f2e00f234ea66b80e8a9bd4dbbc5433926191f",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"mozilla/invalid-this.html": [
|
"mozilla/invalid-this.html": [
|
||||||
|
@ -32904,11 +32904,11 @@
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"mozilla/window_performance.html": [
|
"mozilla/window_performance.html": [
|
||||||
"6b96c18b3cdef8b8bce294f1b45ce09192b00cd0",
|
"690870b7080e179481ca0255f7c30337e8b6636a",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"mozilla/window_performance_topLevelDomComplete.html": [
|
"mozilla/window_performance_topLevelDomComplete.html": [
|
||||||
"ce2431a7279e7cefa9e8032edabe276ac5deb227",
|
"50bbc2917b5ac900b5061a0b2c30b6c1fef1067e",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"mozilla/window_requestAnimationFrame.html": [
|
"mozilla/window_requestAnimationFrame.html": [
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[window_performance.html]
|
||||||
|
[window_performance]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -181,10 +181,11 @@ test_interfaces([
|
||||||
"PerformanceEntry",
|
"PerformanceEntry",
|
||||||
"PerformanceMark",
|
"PerformanceMark",
|
||||||
"PerformanceMeasure",
|
"PerformanceMeasure",
|
||||||
|
"PerformanceNavigationTiming",
|
||||||
"PerformanceObserver",
|
"PerformanceObserver",
|
||||||
"PerformanceObserverEntryList",
|
"PerformanceObserverEntryList",
|
||||||
"PerformancePaintTiming",
|
"PerformancePaintTiming",
|
||||||
"PerformanceTiming",
|
"PerformanceResourceTiming",
|
||||||
"Plugin",
|
"Plugin",
|
||||||
"PluginArray",
|
"PluginArray",
|
||||||
"PopStateEvent",
|
"PopStateEvent",
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue