aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--components/net/fetch/methods.rs14
-rw-r--r--components/net/http_cache.rs15
-rw-r--r--components/net/http_loader.rs47
-rw-r--r--components/net/image_cache.rs4
-rw-r--r--components/net/resource_thread.rs15
-rw-r--r--components/net/tests/fetch.rs17
-rw-r--r--components/net/tests/http_loader.rs32
-rw-r--r--components/net/tests/main.rs18
-rw-r--r--components/net/tests/subresource_integrity.rs11
-rw-r--r--components/net_traits/Cargo.toml1
-rw-r--r--components/net_traits/lib.rs84
-rw-r--r--components/net_traits/request.rs9
-rw-r--r--components/net_traits/response.rs15
-rw-r--r--components/script/dom/bindings/trace.rs3
-rw-r--r--components/script/dom/document.rs26
-rw-r--r--components/script/dom/eventsource.rs35
-rw-r--r--components/script/dom/htmlimageelement.rs41
-rw-r--r--components/script/dom/htmlmediaelement.rs50
-rw-r--r--components/script/dom/htmlscriptelement.rs38
-rw-r--r--components/script/dom/mod.rs3
-rw-r--r--components/script/dom/performance.rs64
-rw-r--r--components/script/dom/performanceentry.rs4
-rw-r--r--components/script/dom/performancenavigationtiming.rs126
-rw-r--r--components/script/dom/performanceobserver.rs8
-rw-r--r--components/script/dom/performanceresourcetiming.rs187
-rw-r--r--components/script/dom/servoparser/mod.rs60
-rw-r--r--components/script/dom/webidls/Performance.webidl17
-rw-r--r--components/script/dom/webidls/PerformanceNavigationTiming.webidl32
-rw-r--r--components/script/dom/webidls/PerformanceResourceTiming.webidl35
-rw-r--r--components/script/dom/webidls/PerformanceTiming.webidl35
-rw-r--r--components/script/dom/window.rs6
-rw-r--r--components/script/dom/workerglobalscope.rs6
-rw-r--r--components/script/dom/xmlhttprequest.rs38
-rw-r--r--components/script/fetch.rs39
-rw-r--r--components/script/layout_image.rs41
-rw-r--r--components/script/network_listener.rs41
-rw-r--r--components/script/script_thread.rs17
-rw-r--r--components/script/stylesheet_loader.rs39
-rw-r--r--tests/wpt/include.ini2
-rw-r--r--tests/wpt/metadata/custom-elements/microtasks-and-constructors.html.ini1
-rw-r--r--tests/wpt/metadata/fetch/api/request/request-keepalive-quota.html.ini2
-rw-r--r--tests/wpt/metadata/hr-time/idlharness.any.js.ini26
-rw-r--r--tests/wpt/metadata/hr-time/test_cross_frame_start.html.ini7
-rw-r--r--tests/wpt/metadata/hr-time/timeOrigin.html.ini3
-rw-r--r--tests/wpt/metadata/hr-time/window-worker-timeOrigin.window.js.ini5
-rw-r--r--tests/wpt/metadata/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/parsing.html.ini4
-rw-r--r--tests/wpt/metadata/navigation-timing/dom_interactive_image_document.html.ini5
-rw-r--r--tests/wpt/metadata/navigation-timing/dom_interactive_media_document.html.ini5
-rw-r--r--tests/wpt/metadata/navigation-timing/nav2_idlharness.html.ini45
-rw-r--r--tests/wpt/metadata/navigation-timing/nav2_test_attributes_exist.html.ini3
-rw-r--r--tests/wpt/metadata/navigation-timing/nav2_test_attributes_values.html.ini3
-rw-r--r--tests/wpt/metadata/navigation-timing/nav2_test_instance_accessors.html.ini3
-rw-r--r--tests/wpt/metadata/navigation-timing/nav2_test_navigation_type_navigate.html.ini3
-rw-r--r--tests/wpt/metadata/navigation-timing/nav2_test_redirect_none.html.ini3
-rw-r--r--tests/wpt/metadata/navigation-timing/nav2_test_unique_nav_instances.html.ini3
-rw-r--r--tests/wpt/metadata/navigation-timing/po-navigation.html.ini3
-rw-r--r--tests/wpt/metadata/navigation-timing/test_timing_attributes_exist.html.ini24
-rw-r--r--tests/wpt/metadata/performance-timeline/case-sensitivity.any.js.ini3
-rw-r--r--tests/wpt/metadata/resource-timing/clear_resource_timing_functionality.html.ini8
-rw-r--r--tests/wpt/metadata/resource-timing/idlharness.any.js.ini243
-rw-r--r--tests/wpt/metadata/resource-timing/resource-timing-tojson.html.ini7
-rw-r--r--tests/wpt/metadata/resource-timing/resource-timing.html.ini55
-rw-r--r--tests/wpt/metadata/resource-timing/resource_TAO_cross_origin_redirect_chain.html.ini5
-rw-r--r--tests/wpt/metadata/resource-timing/resource_TAO_null.htm.ini4
-rw-r--r--tests/wpt/metadata/resource-timing/resource_TAO_origin.htm.ini34
-rw-r--r--tests/wpt/metadata/resource-timing/resource_TAO_origin_uppercase.htm.ini4
-rw-r--r--tests/wpt/metadata/resource-timing/resource_TAO_space.htm.ini4
-rw-r--r--tests/wpt/metadata/resource-timing/resource_TAO_zero.htm.ini28
-rw-r--r--tests/wpt/metadata/resource-timing/resource_cached.htm.ini4
-rw-r--r--tests/wpt/metadata/resource-timing/resource_connection_reuse.html.ini4
-rw-r--r--tests/wpt/metadata/resource-timing/resource_dedicated_worker.html.ini4
-rw-r--r--tests/wpt/metadata/resource-timing/resource_dynamic_insertion.html.ini13
-rw-r--r--tests/wpt/metadata/resource-timing/resource_ignore_data_url.html.ini4
-rw-r--r--tests/wpt/metadata/resource-timing/resource_ignore_failures.html.ini4
-rw-r--r--tests/wpt/metadata/resource-timing/resource_initiator_types.html.ini7
-rw-r--r--tests/wpt/metadata/resource-timing/resource_memory_cached.sub.html.ini20
-rw-r--r--tests/wpt/metadata/resource-timing/resource_redirects.html.ini19
-rw-r--r--tests/wpt/metadata/resource-timing/resource_reparenting.html.ini7
-rw-r--r--tests/wpt/metadata/resource-timing/resource_script_types.html.ini31
-rw-r--r--tests/wpt/metadata/resource-timing/resource_subframe_self_navigation.html.ini13
-rw-r--r--tests/wpt/metadata/resource-timing/resource_timing.worker.js.ini4
-rw-r--r--tests/wpt/metadata/resource-timing/resource_timing_TAO_cross_origin_redirect.html.ini4
-rw-r--r--tests/wpt/metadata/resource-timing/resource_timing_buffer_full_eventually.html.ini5
-rw-r--r--tests/wpt/metadata/resource-timing/resource_timing_buffer_full_when_populate_entries.html.ini10
-rw-r--r--tests/wpt/metadata/resource-timing/resource_timing_buffer_full_when_shrink_buffer_size.html.ini7
-rw-r--r--tests/wpt/metadata/resource-timing/resource_timing_cross_origin_redirect.html.ini4
-rw-r--r--tests/wpt/metadata/resource-timing/resource_timing_cross_origin_redirect_chain.html.ini5
-rw-r--r--tests/wpt/metadata/resource-timing/resource_timing_same_origin_redirect.html.ini4
-rw-r--r--tests/wpt/metadata/resource-timing/resource_timing_store_and_clear_during_callback.html.ini28
-rw-r--r--tests/wpt/metadata/resource-timing/single-entry-per-resource.html.ini7
-rw-r--r--tests/wpt/metadata/resource-timing/test_resource_timing.html.ini77
-rw-r--r--tests/wpt/metadata/workers/baseurl/alpha/import-in-moduleworker.html.ini4
-rw-r--r--tests/wpt/metadata/workers/baseurl/alpha/sharedworker-in-worker.html.ini4
-rw-r--r--tests/wpt/metadata/workers/semantics/multiple-workers/005.html.ini5
-rw-r--r--tests/wpt/metadata/workers/worker-performance.worker.js.ini25
-rw-r--r--tests/wpt/metadata/xhr/sync-no-timeout.any.js.ini4
-rw-r--r--tests/wpt/mozilla/meta/MANIFEST.json8
-rw-r--r--tests/wpt/mozilla/meta/mozilla/window_performance.html.ini4
-rw-r--r--tests/wpt/mozilla/tests/mozilla/interfaces.html3
-rw-r--r--tests/wpt/mozilla/tests/mozilla/interfaces.worker.js1
-rw-r--r--tests/wpt/mozilla/tests/mozilla/window_performance.html8
-rw-r--r--tests/wpt/mozilla/tests/mozilla/window_performance_topLevelDomComplete.html33
103 files changed, 1881 insertions, 322 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e6f61bfcdb5..d62bee3ddc8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2591,6 +2591,7 @@ dependencies = [
"servo_config 0.0.1",
"servo_url 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)",
"uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_api 0.57.2 (git+https://github.com/servo/webrender)",
diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs
index 3687f249112..70dcf4d7983 100644
--- a/components/net/fetch/methods.rs
+++ b/components/net/fetch/methods.rs
@@ -22,7 +22,7 @@ use mime_guess::guess_mime_type;
use net_traits::request::{CredentialsMode, Destination, Referrer, Request, RequestMode};
use net_traits::request::{Origin, ResponseTainting, Window};
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 std::borrow::Cow;
use std::fs::File;
@@ -55,6 +55,7 @@ pub struct FetchContext {
pub devtools_chan: Option<Sender<DevtoolsControlMsg>>,
pub filemanager: FileManager,
pub cancellation_listener: Arc<Mutex<CancellationListener>>,
+ pub timing: Arc<Mutex<ResourceFetchTiming>>,
}
pub struct CancellationListener {
@@ -503,7 +504,7 @@ fn scheme_fetch(
match url.scheme() {
"about" if url.path() == "blank" => {
- let mut response = Response::new(url);
+ let mut response = Response::new(url, ResourceFetchTiming::new(request.timing_type()));
response
.headers
.typed_insert(ContentType::from(mime::TEXT_HTML_UTF_8));
@@ -517,7 +518,8 @@ fn scheme_fetch(
"data" => match decode(&url) {
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.headers.typed_insert(ContentType::from(mime));
response
@@ -537,7 +539,8 @@ fn scheme_fetch(
if let Ok(file) = File::open(file_path.clone()) {
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));
let (done_sender, done_receiver) = unbounded();
@@ -656,7 +659,8 @@ fn scheme_fetch(
match load_blob_sync(url.clone(), context.filemanager.clone()) {
Ok((headers, bytes)) => {
- let mut response = Response::new(url);
+ let mut response =
+ Response::new(url, ResourceFetchTiming::new(request.timing_type()));
response.headers = headers;
*response.body.lock().unwrap() = ResponseBody::Done(bytes);
response
diff --git a/components/net/http_cache.rs b/components/net/http_cache.rs
index a12c935d51d..a91fb6f5180 100644
--- a/components/net/http_cache.rs
+++ b/components/net/http_cache.rs
@@ -20,7 +20,7 @@ use malloc_size_of::{
};
use net_traits::request::Request;
use net_traits::response::{HttpsState, Response, ResponseBody};
-use net_traits::{FetchMetadata, Metadata};
+use net_traits::{FetchMetadata, Metadata, ResourceFetchTiming};
use servo_arc::Arc;
use servo_config::prefs::PREFS;
use servo_url::ServoUrl;
@@ -302,7 +302,11 @@ fn create_cached_response(
cached_headers: &HeaderMap,
done_chan: &mut DoneChannel,
) -> 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.body = cached_resource.body.clone();
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.
// 1. update the headers of the cached resource.
// 2. return a response, constructed from the cached resource.
- let mut constructed_response =
- Response::new(cached_resource.data.metadata.data.final_url.clone());
+ let resource_timing = ResourceFetchTiming::new(request.timing_type());
+ 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.status = cached_resource.data.status.clone();
constructed_response.https_state = cached_resource.data.https_state.clone();
diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs
index e15e6ba4d35..66bdce34f89 100644
--- a/components/net/http_loader.rs
+++ b/components/net/http_loader.rs
@@ -43,6 +43,7 @@ use net_traits::request::{CacheMode, CredentialsMode, Destination, Origin};
use net_traits::request::{RedirectMode, Referrer, Request, RequestMode};
use net_traits::request::{ResponseTainting, ServiceWorkersMode};
use net_traits::response::{HttpsState, Response, ResponseBody, ResponseType};
+use net_traits::ResourceAttribute;
use net_traits::{CookieSource, FetchMetadata, NetworkError, ReferrerPolicy};
use openssl::ssl::SslConnectorBuilder;
use servo_url::{ImmutableOrigin, ServoUrl};
@@ -408,14 +409,8 @@ fn obtain_response(
},
}
- if log_enabled!(log::Level::Info) {
- info!("{} {}", method, url);
- for header in headers.iter() {
- info!(" - {:?}", header);
- }
- info!("{:?}", data);
- }
-
+ // TODO(#21261) connect_start: set if a persistent connection is *not* used and the last non-redirected
+ // fetch passes the timing allow check
let connect_start = precise_time_ms();
// https://url.spec.whatwg.org/#percent-encoded-bytes
let request = HyperRequest::builder()
@@ -435,6 +430,8 @@ fn obtain_response(
Err(e) => return Box::new(future::result(Err(NetworkError::from_http_error(&e)))),
};
*request.headers_mut() = headers.clone();
+
+ //TODO(#21262) connect_end
let connect_end = precise_time_ms();
let request_id = request_id.map(|v| v.to_owned());
@@ -449,6 +446,8 @@ fn obtain_response(
.and_then(move |res| {
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 {
if let Some(pipeline_id) = pipeline_id {
Some(prepare_devtools_request(
@@ -483,6 +482,7 @@ fn obtain_response(
})
.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)
@@ -571,6 +571,19 @@ pub fn http_fetch(
}
// 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(
request,
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
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
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((
res.status(),
res.status().canonical_reason().unwrap_or("").into(),
@@ -1224,6 +1252,7 @@ fn http_network_fetch(
FetchMetadata::Unfiltered(m) => m,
FetchMetadata::Filtered { unsafe_, .. } => unsafe_,
};
+
let devtools_sender = context.devtools_chan.clone();
let meta_status = meta.status.clone();
let meta_headers = meta.headers.clone();
diff --git a/components/net/image_cache.rs b/components/net/image_cache.rs
index e72cd27e3da..7c225d94937 100644
--- a/components/net/image_cache.rs
+++ b/components/net/image_cache.rs
@@ -503,11 +503,11 @@ impl ImageCache for ImageCacheImpl {
(FetchResponseMsg::ProcessResponseEOF(result), key) => {
debug!("Received EOF for {:?}", key);
match result {
- Ok(()) => {
+ Ok(_) => {
let bytes = {
let mut store = self.store.lock().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);
pending_load.bytes.mark_complete()
};
diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs
index 8c2bad33b41..3c366201d95 100644
--- a/components/net/resource_thread.rs
+++ b/components/net/resource_thread.rs
@@ -22,13 +22,14 @@ use embedder_traits::EmbedderProxy;
use hyper_serde::Serde;
use ipc_channel::ipc::{self, IpcReceiver, IpcReceiverSet, IpcSender};
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::storage_thread::StorageThreadMsg;
use net_traits::WebSocketNetworkEvent;
-use net_traits::{CookieSource, CoreResourceThread};
-use net_traits::{CoreResourceMsg, CustomResponseMediator, FetchChannels};
+use net_traits::{CookieSource, CoreResourceMsg, CoreResourceThread};
+use net_traits::{CustomResponseMediator, FetchChannels};
use net_traits::{FetchResponseMsg, ResourceThreads, WebSocketDomAction};
+use net_traits::{ResourceFetchTiming, ResourceTimingType};
use profile_traits::mem::ProfilerChan as MemProfilerChan;
use profile_traits::mem::{Report, ReportKind, ReportsChan};
use profile_traits::time::ProfilerChan;
@@ -440,6 +441,11 @@ impl CoreResourceManager {
let dc = self.devtools_chan.clone();
let filemanager = self.filemanager.clone();
+ let timing_type = match req_init.destination {
+ Destination::Document => ResourceTimingType::Navigation,
+ _ => ResourceTimingType::Resource,
+ };
+
thread::Builder::new()
.name(format!("fetch thread for {}", req_init.url))
.spawn(move || {
@@ -456,11 +462,12 @@ impl CoreResourceManager {
cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(
cancel_chan,
))),
+ timing: Arc::new(Mutex::new(ResourceFetchTiming::new(request.timing_type()))),
};
match res_init_ {
Some(res_init) => {
- let response = Response::from_init(res_init);
+ let response = Response::from_init(res_init, timing_type);
http_redirect_fetch(
&mut request,
&mut CorsCache::new(),
diff --git a/components/net/tests/fetch.rs b/components/net/tests/fetch.rs
index 04f3828c2c6..51f25059ad1 100644
--- a/components/net/tests/fetch.rs
+++ b/components/net/tests/fetch.rs
@@ -35,9 +35,9 @@ use net::hsts::HstsEntry;
use net::test::HttpState;
use net_traits::request::{Destination, Origin, RedirectMode, Referrer, Request, RequestMode};
use net_traits::response::{CacheState, Response, ResponseBody, ResponseType};
-use net_traits::IncludeSubdomains;
-use net_traits::NetworkError;
-use net_traits::ReferrerPolicy;
+use net_traits::{
+ IncludeSubdomains, NetworkError, ReferrerPolicy, ResourceFetchTiming, ResourceTimingType,
+};
use servo_url::{ImmutableOrigin, ServoUrl};
use std::fs::File;
use std::io::Read;
@@ -127,7 +127,7 @@ fn test_fetch_blob() {
use ipc_channel::ipc;
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 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 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());
@@ -649,12 +649,15 @@ fn test_fetch_with_hsts() {
.unwrap();
let ssl_client = create_ssl_connector_builder(&ca_content);
- let context = FetchContext {
+ let mut context = FetchContext {
state: Arc::new(HttpState::new(ssl_client)),
user_agent: DEFAULT_USER_AGENT.into(),
devtools_chan: None,
filemanager: FileManager::new(create_embedder_proxy()),
cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(None))),
+ timing: Arc::new(Mutex::new(ResourceFetchTiming::new(
+ ResourceTimingType::Navigation,
+ ))),
};
{
@@ -668,7 +671,7 @@ fn test_fetch_with_hsts() {
request.referrer = Referrer::NoReferrer;
// Set the flag.
request.local_urls_only = false;
- let response = fetch_with_context(&mut request, &context);
+ let response = fetch_with_context(&mut request, &mut context);
server.close();
assert_eq!(
response.internal_response.unwrap().url().unwrap().scheme(),
diff --git a/components/net/tests/http_loader.rs b/components/net/tests/http_loader.rs
index b61373d14da..0854844f135 100644
--- a/components/net/tests/http_loader.rs
+++ b/components/net/tests/http_loader.rs
@@ -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),
..RequestInit::default()
});
- let context = new_fetch_context(None, None);
- let response = fetch_with_context(&mut request, &context);
+ let mut context = new_fetch_context(None, None);
+ let response = fetch_with_context(&mut request, &mut context);
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 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);
@@ -637,7 +637,7 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_
credentials_mode: CredentialsMode::Include,
..RequestInit::default()
});
- let response = fetch_with_context(&mut request, &context);
+ let response = fetch_with_context(&mut request, &mut context);
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 context = new_fetch_context(None, None);
+ let mut context = new_fetch_context(None, None);
{
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,
..RequestInit::default()
});
- let response = fetch_with_context(&mut request, &context);
+ let response = fetch_with_context(&mut request, &mut context);
let _ = server.close();
@@ -718,7 +718,7 @@ fn test_load_sends_cookie_if_nonhttp() {
};
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();
@@ -741,7 +741,7 @@ fn test_load_sends_cookie_if_nonhttp() {
credentials_mode: CredentialsMode::Include,
..RequestInit::default()
});
- let response = fetch_with_context(&mut request, &context);
+ let response = fetch_with_context(&mut request, &mut context);
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 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);
@@ -781,7 +781,7 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl(
credentials_mode: CredentialsMode::Include,
..RequestInit::default()
});
- let response = fetch_with_context(&mut request, &context);
+ let response = fetch_with_context(&mut request, &mut context);
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 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);
@@ -833,7 +833,7 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() {
credentials_mode: CredentialsMode::Include,
..RequestInit::default()
});
- let response = fetch_with_context(&mut request, &context);
+ let response = fetch_with_context(&mut request, &mut context);
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();
*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 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,
..RequestInit::default()
});
- let response = fetch_with_context(&mut request, &context);
+ let response = fetch_with_context(&mut request, &mut context);
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,
..RequestInit::default()
});
- let context = new_fetch_context(None, None);
+ let mut context = new_fetch_context(None, None);
let auth_entry = AuthCacheEntry {
user_name: "username".to_owned(),
@@ -1370,7 +1370,7 @@ fn test_if_auth_creds_not_in_url_but_in_cache_it_sets_it() {
.entries
.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();
diff --git a/components/net/tests/main.rs b/components/net/tests/main.rs
index 4440506caac..1580eb8310a 100644
--- a/components/net/tests/main.rs
+++ b/components/net/tests/main.rs
@@ -35,7 +35,7 @@ use net::filemanager_thread::FileManager;
use net::test::HttpState;
use net_traits::request::Request;
use net_traits::response::Response;
-use net_traits::FetchTaskTarget;
+use net_traits::{FetchTaskTarget, ResourceFetchTiming, ResourceTimingType};
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use servo_url::ServoUrl;
use std::net::TcpListener as StdTcpListener;
@@ -93,6 +93,9 @@ fn new_fetch_context(
devtools_chan: dc,
filemanager: FileManager::new(sender),
cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(None))),
+ timing: Arc::new(Mutex::new(ResourceFetchTiming::new(
+ ResourceTimingType::Navigation,
+ ))),
}
}
impl FetchTaskTarget for FetchResponseCollector {
@@ -107,14 +110,14 @@ impl FetchTaskTarget for FetchResponseCollector {
}
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 mut target = FetchResponseCollector { sender: sender };
- methods::fetch(request, &mut target, context);
+ methods::fetch(request, &mut target, &mut context);
receiver.recv().unwrap()
}
@@ -123,7 +126,12 @@ fn fetch_with_cors_cache(request: &mut Request, cache: &mut CorsCache) -> Respon
let (sender, receiver) = unbounded();
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()
}
diff --git a/components/net/tests/subresource_integrity.rs b/components/net/tests/subresource_integrity.rs
index a256734113f..ff6ca3d67ad 100644
--- a/components/net/tests/subresource_integrity.rs
+++ b/components/net/tests/subresource_integrity.rs
@@ -5,6 +5,7 @@
use net::subresource_integrity::{get_prioritized_hash_function, get_strongest_metadata, SriEntry};
use net::subresource_integrity::{is_response_integrity_valid, parsed_metadata};
use net_traits::response::{Response, ResponseBody};
+use net_traits::{ResourceFetchTiming, ResourceTimingType};
use servo_url::ServoUrl;
#[test]
@@ -70,7 +71,10 @@ fn test_get_strongest_metadata_different_algorithm() {
#[test]
fn test_response_integrity_valid() {
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 =
"sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO";
@@ -83,7 +87,10 @@ fn test_response_integrity_valid() {
#[test]
fn test_response_integrity_invalid() {
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 =
"sha256-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO";
diff --git a/components/net_traits/Cargo.toml b/components/net_traits/Cargo.toml
index 7c40eb55b04..0bba5824d93 100644
--- a/components/net_traits/Cargo.toml
+++ b/components/net_traits/Cargo.toml
@@ -36,6 +36,7 @@ serde = "1.0"
servo_arc = {path = "../servo_arc"}
servo_config = {path = "../config"}
servo_url = {path = "../url"}
+time = "0.1"
url = "1.2"
uuid = {version = "0.7", features = ["v4", "serde"]}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs
index 212b6885f1b..0cf5604de80 100644
--- a/components/net_traits/lib.rs
+++ b/components/net_traits/lib.rs
@@ -35,6 +35,7 @@ use mime::Mime;
use msg::constellation_msg::HistoryStateId;
use servo_url::ServoUrl;
use std::error::Error;
+use time::precise_time_ns;
use url::percent_encoding;
pub mod blob_url_store;
@@ -157,7 +158,7 @@ pub enum FetchResponseMsg {
// todo: send more info about the response (or perhaps the entire Response)
ProcessResponse(Result<FetchMetadata, NetworkError>),
ProcessResponseChunk(Vec<u8>),
- ProcessResponseEOF(Result<(), NetworkError>),
+ ProcessResponseEOF(Result<ResourceFetchTiming, NetworkError>),
}
pub trait FetchTaskTarget {
@@ -207,7 +208,10 @@ pub trait FetchResponseListener {
fn process_request_eof(&mut self);
fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>);
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> {
@@ -231,7 +235,9 @@ impl FetchTaskTarget for IpcSender<FetchResponseMsg> {
if let Some(e) = response.get_network_error() {
let _ = self.send(FetchResponseMsg::ProcessResponseEOF(Err(e.clone())));
} 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::ProcessResponse(meta) => listener.process_response(meta),
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,
}
+#[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.
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
pub struct Metadata {
@@ -449,6 +520,8 @@ pub struct Metadata {
/// Referrer Policy of the Request used to obtain Response
pub referrer_policy: Option<ReferrerPolicy>,
+ /// Performance information for navigation events
+ pub timing: Option<ResourceFetchTiming>,
}
impl Metadata {
@@ -465,6 +538,7 @@ impl Metadata {
https_state: HttpsState::None,
referrer: None,
referrer_policy: None,
+ timing: None,
}
}
@@ -523,7 +597,7 @@ pub fn load_whole_resource(
})
},
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::ProcessResponseEOF(Err(e)) => return Err(e),
}
diff --git a/components/net_traits/request.rs b/components/net_traits/request.rs
index 1296ad2a193..260aeb99b2a 100644
--- a/components/net_traits/request.rs
+++ b/components/net_traits/request.rs
@@ -3,6 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::ReferrerPolicy;
+use crate::ResourceTimingType;
use http::HeaderMap;
use hyper::Method;
use msg::constellation_msg::PipelineId;
@@ -365,6 +366,14 @@ impl Request {
_ => false,
}
}
+
+ pub fn timing_type(&self) -> ResourceTimingType {
+ if self.is_navigation_request() {
+ ResourceTimingType::Navigation
+ } else {
+ ResourceTimingType::Resource
+ }
+ }
}
impl Referrer {
diff --git a/components/net_traits/response.rs b/components/net_traits/response.rs
index 88644f80fb0..2b9df272c4d 100644
--- a/components/net_traits/response.rs
+++ b/components/net_traits/response.rs
@@ -5,6 +5,7 @@
//! The [Response](https://fetch.spec.whatwg.org/#responses) object
//! resulting from a [fetch operation](https://fetch.spec.whatwg.org/#concept-fetch)
use crate::{FetchMetadata, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy};
+use crate::{ResourceFetchTiming, ResourceTimingType};
use headers_core::HeaderMapExt;
use headers_ext::{AccessControlExposeHeaders, ContentType};
use http::{HeaderMap, StatusCode};
@@ -119,10 +120,12 @@ pub struct Response {
/// https://fetch.spec.whatwg.org/#concept-response-aborted
#[ignore_malloc_size_of = "AtomicBool heap size undefined"]
pub aborted: Arc<AtomicBool>,
+ /// track network metrics
+ pub resource_timing: ResourceFetchTiming,
}
impl Response {
- pub fn new(url: ServoUrl) -> Response {
+ pub fn new(url: ServoUrl, resource_timing: ResourceFetchTiming) -> Response {
Response {
response_type: ResponseType::Default,
termination_reason: None,
@@ -141,11 +144,12 @@ impl Response {
internal_response: None,
return_internal: true,
aborted: Arc::new(AtomicBool::new(false)),
+ resource_timing: resource_timing,
}
}
- pub fn from_init(init: ResponseInit) -> Response {
- let mut res = Response::new(init.url);
+ pub fn from_init(init: ResponseInit, resource_timing_type: ResourceTimingType) -> Response {
+ let mut res = Response::new(init.url, ResourceFetchTiming::new(resource_timing_type));
res.location_url = init.location_url;
res.headers = init.headers;
res.referrer = init.referrer;
@@ -174,6 +178,7 @@ impl Response {
internal_response: None,
return_internal: true,
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`.
/// Do not use with type Error or Default
#[cfg_attr(rustfmt, rustfmt_skip)]
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 62a2727cade..1b430cb12ff 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -80,7 +80,7 @@ use net_traits::request::{Request, RequestInit};
use net_traits::response::HttpsState;
use net_traits::response::{Response, ResponseBody};
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 profile_traits::mem::ProfilerChan as MemProfilerChan;
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!(Mutex<MediaFrameRenderer>);
unsafe_no_jsmanaged_fields!(RenderApiSender);
+unsafe_no_jsmanaged_fields!(ResourceFetchTiming);
unsafe impl<'a> JSTraceable for &'a str {
#[inline]
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 367ce9e2377..e15d735527b 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -356,6 +356,8 @@ pub struct Document {
top_level_dom_complete: Cell<u64>,
load_event_start: 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_state: Cell<HttpsState>,
/// The document's origin.
@@ -406,6 +408,8 @@ pub struct Document {
fired_unload: Cell<bool>,
/// List of responsive images
responsive_images: DomRefCell<Vec<Dom<HTMLImageElement>>>,
+ /// Number of redirects for the document load
+ redirect_count: Cell<u16>,
}
#[derive(JSTraceable, MallocSizeOf)]
@@ -2290,6 +2294,14 @@ impl Document {
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) {
if self.get_interactive_metrics().needs_tti() {
self.tti_window.borrow_mut().start_window();
@@ -2654,6 +2666,8 @@ impl Document {
top_level_dom_complete: Cell::new(Default::default()),
load_event_start: 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),
origin: origin,
referrer: referrer,
@@ -2674,6 +2688,7 @@ impl Document {
salvageable: Cell::new(true),
fired_unload: Cell::new(false),
responsive_images: Default::default(),
+ redirect_count: Cell::new(0),
}
}
@@ -2739,6 +2754,14 @@ impl 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> {
let doc = self.GetDocumentElement();
let maybe_node = doc.r().map(Castable::upcast::<Node>);
@@ -4268,6 +4291,9 @@ impl DocumentMethods for Document {
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();
// Step 7
diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs
index 4484d217752..10c912fb8e4 100644
--- a/components/script/dom/eventsource.rs
+++ b/components/script/dom/eventsource.rs
@@ -16,8 +16,9 @@ use crate::dom::event::Event;
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use crate::dom::messageevent::MessageEvent;
+use crate::dom::performanceresourcetiming::InitiatorType;
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::timers::OneshotTimerCallback;
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::{CoreResourceMsg, FetchChannels, FetchMetadata};
use net_traits::{FetchResponseListener, FetchResponseMsg, NetworkError};
+use net_traits::{ResourceFetchTiming, ResourceTimingType};
use servo_atoms::Atom;
use servo_url::ServoUrl;
use std::cell::Cell;
@@ -91,6 +93,8 @@ struct EventSourceContext {
event_type: String,
data: String,
last_event_id: String,
+
+ resource_timing: ResourceFetchTiming,
}
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() {
self.parse("\u{FFFD}".chars());
}
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 {
@@ -463,6 +489,10 @@ impl EventSource {
self.request.borrow().clone().unwrap()
}
+ pub fn url(&self) -> &ServoUrl {
+ &self.url
+ }
+
// https://html.spec.whatwg.org/multipage/#dom-eventsource
pub fn Constructor(
global: &GlobalScope,
@@ -533,6 +563,7 @@ impl EventSource {
event_type: String::new(),
data: String::new(),
last_event_id: String::new(),
+ resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
};
let listener = NetworkListener {
context: Arc::new(Mutex::new(context)),
diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs
index 287688193c0..b07166fde81 100644
--- a/components/script/dom/htmlimageelement.rs
+++ b/components/script/dom/htmlimageelement.rs
@@ -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::event::{Event, EventBubbles, EventCancelable};
use crate::dom::eventtarget::EventTarget;
+use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlareaelement::HTMLAreaElement;
use crate::dom::htmlelement::HTMLElement;
use crate::dom::htmlformelement::{FormControl, HTMLFormElement};
@@ -33,15 +34,17 @@ use crate::dom::htmlpictureelement::HTMLPictureElement;
use crate::dom::htmlsourceelement::HTMLSourceElement;
use crate::dom::mouseevent::MouseEvent;
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::values::UNSIGNED_LONG_MAX;
use crate::dom::virtualmethods::VirtualMethods;
use crate::dom::window::Window;
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::task_source::TaskSource;
use cssparser::{Parser, ParserInput};
+
use dom_struct::dom_struct;
use euclid::Point2D;
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::request::RequestInit;
use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError};
+use net_traits::{ResourceFetchTiming, ResourceTimingType};
use num_traits::ToPrimitive;
use servo_url::origin::MutableOrigin;
use servo_url::ServoUrl;
@@ -164,6 +168,11 @@ struct ImageContext {
id: PendingImageId,
/// Used to mark abort
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 {
@@ -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
.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 {
@@ -306,6 +340,9 @@ impl HTMLImageElement {
status: Ok(()),
id: id,
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();
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs
index 8092b4a90eb..b5cc9d9b1fd 100644
--- a/components/script/dom/htmlmediaelement.rs
+++ b/components/script/dom/htmlmediaelement.rs
@@ -25,16 +25,18 @@ use crate::dom::blob::Blob;
use crate::dom::document::Document;
use crate::dom::element::{AttributeMutation, Element};
use crate::dom::eventtarget::EventTarget;
+use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlelement::HTMLElement;
use crate::dom::htmlsourceelement::HTMLSourceElement;
use crate::dom::htmlvideoelement::HTMLVideoElement;
use crate::dom::mediaerror::MediaError;
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::virtualmethods::VirtualMethods;
use crate::fetch::FetchCanceller;
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::task_source::TaskSource;
use dom_struct::dom_struct;
@@ -46,8 +48,8 @@ use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use mime::{self, Mime};
use net_traits::request::{CredentialsMode, Destination, RequestInit};
-use net_traits::NetworkError;
use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseListener, Metadata};
+use net_traits::{NetworkError, ResourceFetchTiming, ResourceTimingType};
use script_layout_interface::HTMLMediaData;
use servo_media::player::frame::{Frame, FrameRenderer};
use servo_media::player::{PlaybackState, Player, PlayerEvent, StreamType};
@@ -706,7 +708,10 @@ impl HTMLMediaElement {
..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 window = window_from_node(self);
let (task_source, canceller) = window
@@ -1459,6 +1464,10 @@ struct HTMLMediaElementContext {
next_progress_event: Timespec,
/// True if this response is invalid and should be ignored.
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
@@ -1527,7 +1536,7 @@ impl FetchResponseListener for HTMLMediaElementContext {
}
// 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 {
// An error was received previously, skip processing the payload.
return;
@@ -1579,6 +1588,35 @@ impl FetchResponseListener for HTMLMediaElementContext {
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 {
@@ -1589,13 +1627,15 @@ impl PreInvoke for HTMLMediaElementContext {
}
impl HTMLMediaElementContext {
- fn new(elem: &HTMLMediaElement) -> HTMLMediaElementContext {
+ fn new(elem: &HTMLMediaElement, url: ServoUrl) -> HTMLMediaElementContext {
HTMLMediaElementContext {
elem: Trusted::new(elem),
metadata: None,
generation_id: elem.generation_id.get(),
next_progress_event: time::get_time() + Duration::milliseconds(350),
ignore_response: false,
+ resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
+ url: url,
}
}
}
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs
index bc70965b1ab..a76f506f352 100644
--- a/components/script/dom/htmlscriptelement.rs
+++ b/components/script/dom/htmlscriptelement.rs
@@ -23,8 +23,9 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlelement::HTMLElement;
use crate::dom::node::{document_from_node, window_from_node};
use crate::dom::node::{ChildrenMutation, CloneChildrenFlag, Node};
+use crate::dom::performanceresourcetiming::InitiatorType;
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 encoding_rs::Encoding;
use html5ever::{LocalName, Prefix};
@@ -33,6 +34,7 @@ use ipc_channel::router::ROUTER;
use js::jsval::UndefinedValue;
use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestInit, RequestMode};
use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
+use net_traits::{ResourceFetchTiming, ResourceTimingType};
use servo_atoms::Atom;
use servo_config::opts;
use servo_url::ServoUrl;
@@ -166,6 +168,8 @@ struct ScriptContext {
url: ServoUrl,
/// Indicates whether the request failed, and why
status: Result<(), NetworkError>,
+ /// Timing object for this resource
+ resource_timing: ResourceFetchTiming,
}
impl FetchResponseListener for ScriptContext {
@@ -208,7 +212,7 @@ impl FetchResponseListener for ScriptContext {
/// <https://html.spec.whatwg.org/multipage/#fetch-a-classic-script>
/// step 4-9
- fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
+ fn process_response_eof(&mut self, response: Result<ResourceFetchTiming, NetworkError>) {
// Step 5.
let load = response.and(self.status.clone()).map(|_| {
let metadata = self.metadata.take().unwrap();
@@ -241,6 +245,35 @@ impl FetchResponseListener for ScriptContext {
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 {}
@@ -290,6 +323,7 @@ fn fetch_a_classic_script(
metadata: None,
url: url.clone(),
status: Ok(()),
+ resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
}));
let (action_sender, action_receiver) = ipc::channel().unwrap();
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index c03a5a5206f..b9a9bc60663 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -415,10 +415,11 @@ pub mod performance;
pub mod performanceentry;
pub mod performancemark;
pub mod performancemeasure;
+pub mod performancenavigationtiming;
pub mod performanceobserver;
pub mod performanceobserverentrylist;
pub mod performancepainttiming;
-pub mod performancetiming;
+pub mod performanceresourcetiming;
pub mod permissions;
pub mod permissionstatus;
pub mod plugin;
diff --git a/components/script/dom/performance.rs b/components/script/dom/performance.rs
index f5d041d2903..857dbe569b6 100644
--- a/components/script/dom/performance.rs
+++ b/components/script/dom/performance.rs
@@ -11,15 +11,16 @@ use crate::dom::bindings::codegen::Bindings::PerformanceBinding::{
use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::num::Finite;
-use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
-use crate::dom::bindings::root::{Dom, DomRoot};
+use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
+use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
+use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use crate::dom::performanceentry::PerformanceEntry;
use crate::dom::performancemark::PerformanceMark;
use crate::dom::performancemeasure::PerformanceMeasure;
+use crate::dom::performancenavigationtiming::PerformanceNavigationTiming;
use crate::dom::performanceobserver::PerformanceObserver as DOMPerformanceObserver;
-use crate::dom::performancetiming::PerformanceTiming;
use crate::dom::window::Window;
use dom_struct::dom_struct;
use metrics::ToMs;
@@ -131,8 +132,7 @@ struct PerformanceObserver {
#[dom_struct]
pub struct Performance {
- reflector_: Reflector,
- timing: Option<Dom<PerformanceTiming>>,
+ eventtarget: EventTarget,
entries: DomRefCell<PerformanceEntryList>,
observers: DomRefCell<Vec<PerformanceObserver>>,
pending_notification_observers_task: Cell<bool>,
@@ -140,22 +140,9 @@ pub struct Performance {
}
impl Performance {
- fn new_inherited(
- global: &GlobalScope,
- navigation_start: u64,
- navigation_start_precise: u64,
- ) -> Performance {
+ fn new_inherited(navigation_start_precise: u64) -> Performance {
Performance {
- reflector_: Reflector::new(),
- timing: if global.is::<Window>() {
- Some(Dom::from_ref(&*PerformanceTiming::new(
- global.as_window(),
- navigation_start,
- navigation_start_precise,
- )))
- } else {
- None
- },
+ eventtarget: EventTarget::new_inherited(),
entries: DomRefCell::new(PerformanceEntryList::new(Vec::new())),
observers: DomRefCell::new(Vec::new()),
pending_notification_observers_task: Cell::new(false),
@@ -163,17 +150,9 @@ impl Performance {
}
}
- pub fn new(
- global: &GlobalScope,
- navigation_start: u64,
- navigation_start_precise: u64,
- ) -> DomRoot<Performance> {
+ pub fn new(global: &GlobalScope, navigation_start_precise: u64) -> DomRoot<Performance> {
reflect_dom_object(
- Box::new(Performance::new_inherited(
- global,
- navigation_start,
- navigation_start_precise,
- )),
+ Box::new(Performance::new_inherited(navigation_start_precise)),
global,
PerformanceBinding::Wrap,
)
@@ -296,21 +275,23 @@ impl Performance {
}
fn now(&self) -> f64 {
- let nav_start = match self.timing {
- Some(ref timing) => timing.navigation_start_precise(),
- None => self.navigation_start_precise,
- };
- (time::precise_time_ns() - nav_start).to_ms()
+ (time::precise_time_ns() - self.navigation_start_precise).to_ms()
}
}
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
- fn Timing(&self) -> DomRoot<PerformanceTiming> {
- match self.timing {
- Some(ref timing) => DomRoot::from_ref(&*timing),
- None => unreachable!("Are we trying to expose Performance.timing in workers?"),
+ fn Timing(&self) -> DomRoot<PerformanceNavigationTiming> {
+ let entries = self.GetEntriesByType(DOMString::from("navigation"));
+ if entries.len() > 0 {
+ 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
@@ -318,6 +299,11 @@ impl PerformanceMethods for Performance {
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
fn GetEntries(&self) -> Vec<DomRoot<PerformanceEntry>> {
self.entries
diff --git a/components/script/dom/performanceentry.rs b/components/script/dom/performanceentry.rs
index 7317532f226..334d8b6de85 100644
--- a/components/script/dom/performanceentry.rs
+++ b/components/script/dom/performanceentry.rs
@@ -59,6 +59,10 @@ impl PerformanceEntry {
pub fn start_time(&self) -> f64 {
self.start_time
}
+
+ pub fn duration(&self) -> f64 {
+ self.duration
+ }
}
impl PerformanceEntryMethods for PerformanceEntry {
diff --git a/components/script/dom/performancenavigationtiming.rs b/components/script/dom/performancenavigationtiming.rs
new file mode 100644
index 00000000000..8e9ef66c938
--- /dev/null
+++ b/components/script/dom/performancenavigationtiming.rs
@@ -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)
+ }
+}
diff --git a/components/script/dom/performanceobserver.rs b/components/script/dom/performanceobserver.rs
index cf7ba499f28..dc66e88b5a3 100644
--- a/components/script/dom/performanceobserver.rs
+++ b/components/script/dom/performanceobserver.rs
@@ -22,9 +22,11 @@ use std::rc::Rc;
/// List of allowed performance entry types.
const VALID_ENTRY_TYPES: &'static [&'static str] = &[
- "mark", // User Timing API
- "measure", // User Timing API
- // "resource", XXX Resource Timing API
+ "mark", // User Timing API
+ "measure", // User Timing API
+ "resource", // Resource Timing API
+ "navigation", // Navigation Timing API
+ // "frame", //TODO Frame Timing API
// "server", XXX Server Timing API
"paint", // Paint Timing API
];
diff --git a/components/script/dom/performanceresourcetiming.rs b/components/script/dom/performanceresourcetiming.rs
new file mode 100644
index 00000000000..22842160267
--- /dev/null
+++ b/components/script/dom/performanceresourcetiming.rs
@@ -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)
+ }
+}
diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs
index a023fb19651..3c7e45f91de 100644
--- a/components/script/dom/servoparser/mod.rs
+++ b/components/script/dom/servoparser/mod.rs
@@ -13,7 +13,7 @@ use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use crate::dom::bindings::codegen::Bindings::ServoParserBinding;
use crate::dom::bindings::inheritance::Castable;
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::settings_stack::is_execution_stack_empty;
use crate::dom::bindings::str::DOMString;
@@ -28,6 +28,8 @@ use crate::dom::htmlimageelement::HTMLImageElement;
use crate::dom::htmlscriptelement::{HTMLScriptElement, ScriptResult};
use crate::dom::htmltemplateelement::HTMLTemplateElement;
use crate::dom::node::Node;
+use crate::dom::performanceentry::PerformanceEntry;
+use crate::dom::performancenavigationtiming::PerformanceNavigationTiming;
use crate::dom::processinginstruction::ProcessingInstruction;
use crate::dom::text::Text;
use crate::dom::virtualmethods::vtable_for;
@@ -43,8 +45,10 @@ use hyper_serde::Serde;
use mime::{self, Mime};
use msg::constellation_msg::PipelineId;
use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
-use profile_traits::time::{profile, ProfilerCategory, TimerMetadataReflowType};
-use profile_traits::time::{TimerMetadata, TimerMetadataFrameType};
+use net_traits::{ResourceFetchTiming, ResourceTimingType};
+use profile_traits::time::{
+ profile, ProfilerCategory, TimerMetadata, TimerMetadataFrameType, TimerMetadataReflowType,
+};
use script_traits::DocumentActivity;
use servo_config::prefs::PREFS;
use servo_url::ServoUrl;
@@ -656,6 +660,8 @@ pub struct ParserContext {
id: PipelineId,
/// The URL for this document.
url: ServoUrl,
+ /// timing data for this resource
+ resource_timing: ResourceFetchTiming,
}
impl ParserContext {
@@ -665,6 +671,7 @@ impl ParserContext {
is_synthesized_document: false,
id: id,
url: url,
+ resource_timing: ResourceFetchTiming::new(ResourceTimingType::Navigation),
}
}
}
@@ -792,7 +799,10 @@ impl FetchResponseListener for ParserContext {
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() {
Some(parser) => parser.root(),
None => return,
@@ -801,15 +811,53 @@ impl FetchResponseListener for ParserContext {
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.
- 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);
if !parser.suspended.get() {
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);
}
}
diff --git a/components/script/dom/webidls/Performance.webidl b/components/script/dom/webidls/Performance.webidl
index 85f8fb58b27..52f5c7e1797 100644
--- a/components/script/dom/webidls/Performance.webidl
+++ b/components/script/dom/webidls/Performance.webidl
@@ -10,14 +10,10 @@ typedef double DOMHighResTimeStamp;
typedef sequence<PerformanceEntry> PerformanceEntryList;
[Exposed=(Window, Worker)]
-interface Performance {
+interface Performance : EventTarget {
DOMHighResTimeStamp now();
-};
-
-[Exposed=(Window)]
-partial interface Performance {
- readonly attribute PerformanceTiming timing;
- /* readonly attribute PerformanceNavigation navigation; */
+ readonly attribute DOMHighResTimeStamp timeOrigin;
+ // [Default] object toJSON();
};
// 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 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();
+};
diff --git a/components/script/dom/webidls/PerformanceNavigationTiming.webidl b/components/script/dom/webidls/PerformanceNavigationTiming.webidl
new file mode 100644
index 00000000000..cde173c67e2
--- /dev/null
+++ b/components/script/dom/webidls/PerformanceNavigationTiming.webidl
@@ -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;
+};
diff --git a/components/script/dom/webidls/PerformanceResourceTiming.webidl b/components/script/dom/webidls/PerformanceResourceTiming.webidl
new file mode 100644
index 00000000000..ca8b4c99b81
--- /dev/null
+++ b/components/script/dom/webidls/PerformanceResourceTiming.webidl
@@ -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;
+// };
diff --git a/components/script/dom/webidls/PerformanceTiming.webidl b/components/script/dom/webidls/PerformanceTiming.webidl
deleted file mode 100644
index d2fcb1faec5..00000000000
--- a/components/script/dom/webidls/PerformanceTiming.webidl
+++ /dev/null
@@ -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;
-};
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 338c78111e5..b07998de6d4 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -812,11 +812,7 @@ impl WindowMethods for Window {
fn Performance(&self) -> DomRoot<Performance> {
self.performance.or_init(|| {
let global_scope = self.upcast::<GlobalScope>();
- Performance::new(
- global_scope,
- self.navigation_start.get(),
- self.navigation_start_precise.get(),
- )
+ Performance::new(global_scope, self.navigation_start_precise.get())
})
}
diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs
index fb29bc1c740..99cee52eaa1 100644
--- a/components/script/dom/workerglobalscope.rs
+++ b/components/script/dom/workerglobalscope.rs
@@ -357,11 +357,7 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
fn Performance(&self) -> DomRoot<Performance> {
self.performance.or_init(|| {
let global_scope = self.upcast::<GlobalScope>();
- Performance::new(
- global_scope,
- 0, /* navigation start is not used in workers */
- self.navigation_start_precise,
- )
+ Performance::new(global_scope, self.navigation_start_precise)
})
}
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index 3e1644536ab..18628f27f70 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -28,6 +28,7 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::headers::is_forbidden_header_name;
use crate::dom::htmlformelement::{encode_multipart_form_data, generate_boundary};
use crate::dom::node::Node;
+use crate::dom::performanceresourcetiming::InitiatorType;
use crate::dom::progressevent::ProgressEvent;
use crate::dom::servoparser::ServoParser;
use crate::dom::urlsearchparams::URLSearchParams;
@@ -36,7 +37,7 @@ use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget;
use crate::dom::xmlhttprequestupload::XMLHttpRequestUpload;
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::TaskSourceName;
use crate::timers::{OneshotTimerCallback, OneshotTimerHandle};
@@ -63,6 +64,7 @@ use net_traits::trim_http_whitespace;
use net_traits::CoreResourceMsg::Fetch;
use net_traits::{FetchChannels, FetchMetadata, FilteredMetadata};
use net_traits::{FetchResponseListener, NetworkError, ReferrerPolicy};
+use net_traits::{ResourceFetchTiming, ResourceTimingType};
use script_traits::DocumentActivity;
use servo_atoms::Atom;
use servo_url::ServoUrl;
@@ -95,6 +97,7 @@ struct XHRContext {
gen_id: GenerationId,
buf: DomRefCell<Vec<u8>>,
sync_status: DomRefCell<Option<ErrorResult>>,
+ resource_timing: ResourceFetchTiming,
}
#[derive(Clone)]
@@ -257,13 +260,41 @@ impl XMLHttpRequest {
.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
.xhr
.root()
- .process_response_complete(self.gen_id, response);
+ .process_response_complete(self.gen_id, response.map(|_| ()));
*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 {
@@ -1424,6 +1455,7 @@ impl XMLHttpRequest {
gen_id: self.generation_id.get(),
buf: DomRefCell::new(vec![]),
sync_status: DomRefCell::new(None),
+ resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
}));
let (task_source, script_port) = if self.sync.get() {
diff --git a/components/script/fetch.rs b/components/script/fetch.rs
index 49e441740bc..922ee7d9d03 100644
--- a/components/script/fetch.rs
+++ b/components/script/fetch.rs
@@ -14,11 +14,12 @@ use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::globalscope::GlobalScope;
use crate::dom::headers::Guard;
+use crate::dom::performanceresourcetiming::InitiatorType;
use crate::dom::promise::Promise;
use crate::dom::request::Request;
use crate::dom::response::Response;
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 ipc_channel::ipc;
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::{FetchChannels, FetchResponseListener, NetworkError};
use net_traits::{FetchMetadata, FilteredMetadata, Metadata};
+use net_traits::{ResourceFetchTiming, ResourceTimingType};
use servo_url::ServoUrl;
use std::mem;
use std::rc::Rc;
@@ -37,6 +39,7 @@ struct FetchContext {
fetch_promise: Option<TrustedPromise>,
response_object: Trusted<Response>,
body: Vec<u8>,
+ resource_timing: ResourceFetchTiming,
}
/// RAII fetch canceller object. By default initialized to not having a canceller
@@ -143,6 +146,8 @@ pub fn Fetch(
},
Ok(r) => r.get_request(),
};
+ let timing_type = request.timing_type();
+
let mut request_init = request_init_from_request(request);
// Step 3
@@ -159,6 +164,7 @@ pub fn Fetch(
fetch_promise: Some(TrustedPromise::new(promise.clone())),
response_object: Trusted::new(&*response),
body: vec![],
+ resource_timing: ResourceFetchTiming::new(timing_type),
}));
let listener = NetworkListener {
context: fetch_context,
@@ -250,7 +256,7 @@ impl FetchResponseListener for FetchContext {
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 global = response.global();
let cx = global.get_cx();
@@ -259,6 +265,35 @@ impl FetchResponseListener for FetchContext {
// TODO
// ... 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) {
diff --git a/components/script/layout_image.rs b/components/script/layout_image.rs
index 59dac86e784..e47218cffda 100644
--- a/components/script/layout_image.rs
+++ b/components/script/layout_image.rs
@@ -7,20 +7,28 @@
//! no guarantee that the responsible nodes will still exist in the future if the
//! 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::root::DomRoot;
+use crate::dom::document::Document;
+use crate::dom::globalscope::GlobalScope;
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::router::ROUTER;
use net_traits::image_cache::{ImageCache, PendingImageId};
use net_traits::request::{Destination, RequestInit as FetchRequestInit};
use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg, NetworkError};
+use net_traits::{ResourceFetchTiming, ResourceTimingType};
use servo_url::ServoUrl;
use std::sync::{Arc, Mutex};
struct LayoutImageContext {
id: PendingImageId,
cache: Arc<dyn ImageCache>,
+ resource_timing: ResourceFetchTiming,
+ doc: Trusted<Document>,
}
impl FetchResponseListener for LayoutImageContext {
@@ -36,10 +44,35 @@ impl FetchResponseListener for LayoutImageContext {
.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
.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 {}
@@ -50,9 +83,13 @@ pub fn fetch_image_for_layout(
id: PendingImageId,
cache: Arc<dyn ImageCache>,
) {
+ let document = document_from_node(node);
+
let context = Arc::new(Mutex::new(LayoutImageContext {
id: id,
cache: cache,
+ resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
+ doc: Trusted::new(&document),
}));
let document = document_from_node(node);
diff --git a/components/script/network_listener.rs b/components/script/network_listener.rs
index 99042d42c8d..53e9360eee0 100644
--- a/components/script/network_listener.rs
+++ b/components/script/network_listener.rs
@@ -2,10 +2,16 @@
* 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/. */
+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_source::networking::NetworkingTaskSource;
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};
/// 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 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> {
pub fn notify<A: Action<Listener> + Send + 'static>(&self, action: A) {
let task = ListenerTask {
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 70c541b14c8..21c87d772e9 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -107,7 +107,10 @@ use net_traits::image_cache::{ImageCache, PendingImageResponse};
use net_traits::request::{CredentialsMode, Destination, RedirectMode, RequestInit};
use net_traits::storage_thread::StorageType;
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::time::{self as profile_time, profile, ProfilerCategory};
use script_layout_interface::message::{self, Msg, NewLayoutThreadInfo, ReflowGoal};
@@ -3097,9 +3100,12 @@ impl ScriptThread {
fetch_metadata: Result<FetchMetadata, NetworkError>,
) {
match fetch_metadata {
- Ok(_) => {},
- Err(ref e) => warn!("Network error: {:?}", e),
+ Ok(_) => (),
+ Err(ref e) => {
+ warn!("Network error: {:?}", e);
+ },
};
+
let mut incomplete_parser_contexts = self.incomplete_parser_contexts.borrow_mut();
let parser = incomplete_parser_contexts
.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
.incomplete_parser_contexts
.borrow()
.iter()
.position(|&(pipeline_id, _)| pipeline_id == id);
+
if let Some(idx) = idx {
let (_, mut ctxt) = self.incomplete_parser_contexts.borrow_mut().remove(idx);
ctxt.process_response_eof(eof);
@@ -3161,7 +3168,7 @@ impl ScriptThread {
context.process_response(Ok(FetchMetadata::Unfiltered(meta)));
context.process_response_chunk(chunk);
- context.process_response_eof(Ok(()));
+ context.process_response_eof(Ok(ResourceFetchTiming::new(ResourceTimingType::None)));
}
fn handle_css_error_reporting(
diff --git a/components/script/stylesheet_loader.rs b/components/script/stylesheet_loader.rs
index 38957c8bf0a..88ad87ada22 100644
--- a/components/script/stylesheet_loader.rs
+++ b/components/script/stylesheet_loader.rs
@@ -6,13 +6,16 @@ use crate::document_loader::LoadType;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomObject;
+use crate::dom::bindings::root::DomRoot;
use crate::dom::document::Document;
use crate::dom::element::Element;
use crate::dom::eventtarget::EventTarget;
+use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlelement::HTMLElement;
use crate::dom::htmllinkelement::{HTMLLinkElement, RequestGenerationId};
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 encoding_rs::UTF_8;
use ipc_channel::ipc;
@@ -22,6 +25,7 @@ use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestIni
use net_traits::{
FetchMetadata, FetchResponseListener, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy,
};
+use net_traits::{ResourceFetchTiming, ResourceTimingType};
use parking_lot::RwLock;
use servo_arc::Arc;
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.
/// This is ignored for `HTMLStyleElement` and imports.
request_generation_id: Option<RequestGenerationId>,
+ resource_timing: ResourceFetchTiming,
}
impl PreInvoke for StylesheetContext {}
@@ -108,7 +113,7 @@ impl FetchResponseListener for StylesheetContext {
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 document = self.document.root();
let mut successful = false;
@@ -207,6 +212,35 @@ impl FetchResponseListener for StylesheetContext {
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> {
@@ -241,6 +275,7 @@ impl<'a> StylesheetLoader<'a> {
document: Trusted::new(&*document),
origin_clean: true,
request_generation_id: gen,
+ resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
}));
let (action_sender, action_receiver) = ipc::channel().unwrap();
diff --git a/tests/wpt/include.ini b/tests/wpt/include.ini
index 6282824bebe..9219625bfae 100644
--- a/tests/wpt/include.ini
+++ b/tests/wpt/include.ini
@@ -103,6 +103,8 @@ skip: true
skip: false
[referrer-policy]
skip: false
+[resource-timing]
+ skip: false
[subresource-integrity]
skip: false
[touch-events]
diff --git a/tests/wpt/metadata/custom-elements/microtasks-and-constructors.html.ini b/tests/wpt/metadata/custom-elements/microtasks-and-constructors.html.ini
index b67eb3e525a..cc30607acbd 100644
--- a/tests/wpt/metadata/custom-elements/microtasks-and-constructors.html.ini
+++ b/tests/wpt/metadata/custom-elements/microtasks-and-constructors.html.ini
@@ -7,3 +7,4 @@
[Microtasks evaluate afterward when the stack is not empty using createElement()]
expected: FAIL
+
diff --git a/tests/wpt/metadata/fetch/api/request/request-keepalive-quota.html.ini b/tests/wpt/metadata/fetch/api/request/request-keepalive-quota.html.ini
index 57f7b4fc44f..c2a729a1e63 100644
--- a/tests/wpt/metadata/fetch/api/request/request-keepalive-quota.html.ini
+++ b/tests/wpt/metadata/fetch/api/request/request-keepalive-quota.html.ini
@@ -24,5 +24,3 @@
[A Keep-Alive fetch() with a body over the Quota Limit should reject.]
expected: FAIL
-
-[request-keepalive-quota.html?include=slow-1]
diff --git a/tests/wpt/metadata/hr-time/idlharness.any.js.ini b/tests/wpt/metadata/hr-time/idlharness.any.js.ini
index 9f19d08947f..446960c4847 100644
--- a/tests/wpt/metadata/hr-time/idlharness.any.js.ini
+++ b/tests/wpt/metadata/hr-time/idlharness.any.js.ini
@@ -2,31 +2,21 @@
[idlharness]
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()]
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]
expected: FAIL
[Test default toJSON operation of Performance]
expected: FAIL
+
[idlharness.any.serviceworker.html]
[idlharness]
expected: FAIL
+
[idlharness.any.sharedworker.html]
[idlharness]
expected: FAIL
@@ -42,21 +32,9 @@
[idlharness]
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()]
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]
expected: FAIL
diff --git a/tests/wpt/metadata/hr-time/test_cross_frame_start.html.ini b/tests/wpt/metadata/hr-time/test_cross_frame_start.html.ini
new file mode 100644
index 00000000000..b1f8757f2f6
--- /dev/null
+++ b/tests/wpt/metadata/hr-time/test_cross_frame_start.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/hr-time/timeOrigin.html.ini b/tests/wpt/metadata/hr-time/timeOrigin.html.ini
index 0ac417723d6..dfd84d1f80b 100644
--- a/tests/wpt/metadata/hr-time/timeOrigin.html.ini
+++ b/tests/wpt/metadata/hr-time/timeOrigin.html.ini
@@ -6,6 +6,3 @@
[Window and worker timeOrigins are close when created one after another.]
expected: FAIL
- [Window and worker timeOrigins differ when worker is created after a delay.]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/hr-time/window-worker-timeOrigin.window.js.ini b/tests/wpt/metadata/hr-time/window-worker-timeOrigin.window.js.ini
deleted file mode 100644
index ed7a2abc933..00000000000
--- a/tests/wpt/metadata/hr-time/window-worker-timeOrigin.window.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[window-worker-timeOrigin.window.html]
- type: testharness
- [timeOrigin and now() should be correctly ordered between window and worker]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/parsing.html.ini b/tests/wpt/metadata/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/parsing.html.ini
index 54f6b43a6f2..a3331003f7b 100644
--- a/tests/wpt/metadata/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/parsing.html.ini
+++ b/tests/wpt/metadata/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/parsing.html.ini
@@ -292,7 +292,3 @@
[<meta>: "1\\furl=foo"]
expected: TIMEOUT
-
-[parsing.html?131-last]
-
-[parsing.html?81-90]
diff --git a/tests/wpt/metadata/navigation-timing/dom_interactive_image_document.html.ini b/tests/wpt/metadata/navigation-timing/dom_interactive_image_document.html.ini
new file mode 100644
index 00000000000..ba16ab0609f
--- /dev/null
+++ b/tests/wpt/metadata/navigation-timing/dom_interactive_image_document.html.ini
@@ -0,0 +1,5 @@
+[dom_interactive_image_document.html]
+ expected: ERROR
+ [Test domInteractive on image document]
+ expected: NOTRUN
+
diff --git a/tests/wpt/metadata/navigation-timing/dom_interactive_media_document.html.ini b/tests/wpt/metadata/navigation-timing/dom_interactive_media_document.html.ini
new file mode 100644
index 00000000000..03e4f3cf11c
--- /dev/null
+++ b/tests/wpt/metadata/navigation-timing/dom_interactive_media_document.html.ini
@@ -0,0 +1,5 @@
+[dom_interactive_media_document.html]
+ expected: ERROR
+ [Test domInteractive on media document]
+ expected: NOTRUN
+
diff --git a/tests/wpt/metadata/navigation-timing/nav2_idlharness.html.ini b/tests/wpt/metadata/navigation-timing/nav2_idlharness.html.ini
index 4b0d63606b0..5336f84e3ed 100644
--- a/tests/wpt/metadata/navigation-timing/nav2_idlharness.html.ini
+++ b/tests/wpt/metadata/navigation-timing/nav2_idlharness.html.ini
@@ -1,56 +1,11 @@
[nav2_idlharness.html]
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]
expected: FAIL
[PerformanceNavigationTiming interface: operation toJSON()]
expected: FAIL
- [PerformanceNavigationTiming interface: existence and properties of interface prototype object's @@unscopables property]
- expected: FAIL
-
[Navigation Timing 2 IDL tests]
expected: FAIL
diff --git a/tests/wpt/metadata/navigation-timing/nav2_test_attributes_exist.html.ini b/tests/wpt/metadata/navigation-timing/nav2_test_attributes_exist.html.ini
index d5aa84ebe6f..3f595348569 100644
--- a/tests/wpt/metadata/navigation-timing/nav2_test_attributes_exist.html.ini
+++ b/tests/wpt/metadata/navigation-timing/nav2_test_attributes_exist.html.ini
@@ -1,5 +1,6 @@
[nav2_test_attributes_exist.html]
type: testharness
+ expected: TIMEOUT
[Performance navigation timing entries are observable.]
- expected: FAIL
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/navigation-timing/nav2_test_attributes_values.html.ini b/tests/wpt/metadata/navigation-timing/nav2_test_attributes_values.html.ini
index c70527cfed7..106a2089e22 100644
--- a/tests/wpt/metadata/navigation-timing/nav2_test_attributes_values.html.ini
+++ b/tests/wpt/metadata/navigation-timing/nav2_test_attributes_values.html.ini
@@ -1,5 +1,6 @@
[nav2_test_attributes_values.html]
type: testharness
+ expected: TIMEOUT
[Performance navigation timing instance's value is reasonable.]
- expected: FAIL
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/navigation-timing/nav2_test_instance_accessors.html.ini b/tests/wpt/metadata/navigation-timing/nav2_test_instance_accessors.html.ini
index a75dbdb2c0c..045da4d33d9 100644
--- a/tests/wpt/metadata/navigation-timing/nav2_test_instance_accessors.html.ini
+++ b/tests/wpt/metadata/navigation-timing/nav2_test_instance_accessors.html.ini
@@ -1,5 +1,6 @@
[nav2_test_instance_accessors.html]
type: testharness
+ expected: TIMEOUT
[Performance navigation timing entries are accessible through three different accessors.]
- expected: FAIL
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/navigation-timing/nav2_test_navigation_type_navigate.html.ini b/tests/wpt/metadata/navigation-timing/nav2_test_navigation_type_navigate.html.ini
index e14d5984612..cbe2682faf7 100644
--- a/tests/wpt/metadata/navigation-timing/nav2_test_navigation_type_navigate.html.ini
+++ b/tests/wpt/metadata/navigation-timing/nav2_test_navigation_type_navigate.html.ini
@@ -1,5 +1,6 @@
[nav2_test_navigation_type_navigate.html]
type: testharness
+ expected: TIMEOUT
[Navigation type to be navigate.]
- expected: FAIL
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/navigation-timing/nav2_test_redirect_none.html.ini b/tests/wpt/metadata/navigation-timing/nav2_test_redirect_none.html.ini
index e3727d63e81..617077228e9 100644
--- a/tests/wpt/metadata/navigation-timing/nav2_test_redirect_none.html.ini
+++ b/tests/wpt/metadata/navigation-timing/nav2_test_redirect_none.html.ini
@@ -1,5 +1,6 @@
[nav2_test_redirect_none.html]
type: testharness
+ expected: TIMEOUT
[Naivation without redirects.]
- expected: FAIL
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/navigation-timing/nav2_test_unique_nav_instances.html.ini b/tests/wpt/metadata/navigation-timing/nav2_test_unique_nav_instances.html.ini
index 695df4f36e3..c29f84c38a2 100644
--- a/tests/wpt/metadata/navigation-timing/nav2_test_unique_nav_instances.html.ini
+++ b/tests/wpt/metadata/navigation-timing/nav2_test_unique_nav_instances.html.ini
@@ -1,5 +1,6 @@
[nav2_test_unique_nav_instances.html]
type: testharness
+ expected: TIMEOUT
[Each window has a unique nav timing 2 instance.]
- expected: FAIL
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/navigation-timing/po-navigation.html.ini b/tests/wpt/metadata/navigation-timing/po-navigation.html.ini
index 295e2ccdc3f..3fbca338c46 100644
--- a/tests/wpt/metadata/navigation-timing/po-navigation.html.ini
+++ b/tests/wpt/metadata/navigation-timing/po-navigation.html.ini
@@ -1,4 +1,5 @@
[po-navigation.html]
+ expected: TIMEOUT
[navigation entry is observable]
- expected: FAIL
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/navigation-timing/test_timing_attributes_exist.html.ini b/tests/wpt/metadata/navigation-timing/test_timing_attributes_exist.html.ini
index e72584e33d0..5f256e10605 100644
--- a/tests/wpt/metadata/navigation-timing/test_timing_attributes_exist.html.ini
+++ b/tests/wpt/metadata/navigation-timing/test_timing_attributes_exist.html.ini
@@ -36,3 +36,27 @@
[window.performance.timing.unloadEventStart is defined.]
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
+
diff --git a/tests/wpt/metadata/performance-timeline/case-sensitivity.any.js.ini b/tests/wpt/metadata/performance-timeline/case-sensitivity.any.js.ini
index b86734a2075..66792a7732c 100644
--- a/tests/wpt/metadata/performance-timeline/case-sensitivity.any.js.ini
+++ b/tests/wpt/metadata/performance-timeline/case-sensitivity.any.js.ini
@@ -9,9 +9,6 @@
[case-sensitivity.any.html]
type: testharness
- [getEntriesByType values are case sensitive]
- expected: FAIL
-
[getEntriesByName values are case sensitive]
expected: FAIL
diff --git a/tests/wpt/metadata/resource-timing/clear_resource_timing_functionality.html.ini b/tests/wpt/metadata/resource-timing/clear_resource_timing_functionality.html.ini
new file mode 100644
index 00000000000..e3621276db4
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/clear_resource_timing_functionality.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/idlharness.any.js.ini b/tests/wpt/metadata/resource-timing/idlharness.any.js.ini
new file mode 100644
index 00000000000..e2a7284a204
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/idlharness.any.js.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource-timing-tojson.html.ini b/tests/wpt/metadata/resource-timing/resource-timing-tojson.html.ini
new file mode 100644
index 00000000000..402fec6118d
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource-timing-tojson.html.ini
@@ -0,0 +1,7 @@
+[resource-timing-tojson.html]
+ [Untitled]
+ expected: FAIL
+
+ [Test toJSON() in PerformanceResourceTiming]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/resource-timing/resource-timing.html.ini b/tests/wpt/metadata/resource-timing/resource-timing.html.ini
new file mode 100644
index 00000000000..0ed5d2668f8
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource-timing.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_TAO_cross_origin_redirect_chain.html.ini b/tests/wpt/metadata/resource-timing/resource_TAO_cross_origin_redirect_chain.html.ini
new file mode 100644
index 00000000000..0b889e1068d
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_TAO_cross_origin_redirect_chain.html.ini
@@ -0,0 +1,5 @@
+[resource_TAO_cross_origin_redirect_chain.html]
+ expected: ERROR
+ [There should be one entry.]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/resource-timing/resource_TAO_null.htm.ini b/tests/wpt/metadata/resource-timing/resource_TAO_null.htm.ini
new file mode 100644
index 00000000000..2c100c3d26f
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_TAO_null.htm.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_TAO_origin.htm.ini b/tests/wpt/metadata/resource-timing/resource_TAO_origin.htm.ini
new file mode 100644
index 00000000000..5bc7995d47f
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_TAO_origin.htm.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_TAO_origin_uppercase.htm.ini b/tests/wpt/metadata/resource-timing/resource_TAO_origin_uppercase.htm.ini
new file mode 100644
index 00000000000..7c5b455b088
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_TAO_origin_uppercase.htm.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_TAO_space.htm.ini b/tests/wpt/metadata/resource-timing/resource_TAO_space.htm.ini
new file mode 100644
index 00000000000..d18dd65b509
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_TAO_space.htm.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_TAO_zero.htm.ini b/tests/wpt/metadata/resource-timing/resource_TAO_zero.htm.ini
new file mode 100644
index 00000000000..c64ef4dfc1d
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_TAO_zero.htm.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_cached.htm.ini b/tests/wpt/metadata/resource-timing/resource_cached.htm.ini
new file mode 100644
index 00000000000..aff4156ee6b
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_cached.htm.ini
@@ -0,0 +1,4 @@
+[resource_cached.htm]
+ [There should be two entries]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/resource-timing/resource_connection_reuse.html.ini b/tests/wpt/metadata/resource-timing/resource_connection_reuse.html.ini
new file mode 100644
index 00000000000..1fe5956c6a0
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_connection_reuse.html.ini
@@ -0,0 +1,4 @@
+[resource_connection_reuse.html]
+ [There should be 2 PerformanceEntries]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/resource-timing/resource_dedicated_worker.html.ini b/tests/wpt/metadata/resource-timing/resource_dedicated_worker.html.ini
new file mode 100644
index 00000000000..a0318fd5935
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_dedicated_worker.html.ini
@@ -0,0 +1,4 @@
+[resource_dedicated_worker.html]
+ [There should be six entries: 4 scripts, 1 stylesheet, and the worker itself]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/resource-timing/resource_dynamic_insertion.html.ini b/tests/wpt/metadata/resource-timing/resource_dynamic_insertion.html.ini
new file mode 100644
index 00000000000..c72ce17c457
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_dynamic_insertion.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_ignore_data_url.html.ini b/tests/wpt/metadata/resource-timing/resource_ignore_data_url.html.ini
new file mode 100644
index 00000000000..cca981afd37
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_ignore_data_url.html.ini
@@ -0,0 +1,4 @@
+[resource_ignore_data_url.html]
+ [entries.length == 0]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/resource-timing/resource_ignore_failures.html.ini b/tests/wpt/metadata/resource-timing/resource_ignore_failures.html.ini
new file mode 100644
index 00000000000..71f5fa720e1
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_ignore_failures.html.ini
@@ -0,0 +1,4 @@
+[resource_ignore_failures.html]
+ [entries.length == 0]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/resource-timing/resource_initiator_types.html.ini b/tests/wpt/metadata/resource-timing/resource_initiator_types.html.ini
new file mode 100644
index 00000000000..37136277fe2
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_initiator_types.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_memory_cached.sub.html.ini b/tests/wpt/metadata/resource-timing/resource_memory_cached.sub.html.ini
new file mode 100644
index 00000000000..7e8a2a7e473
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_memory_cached.sub.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_redirects.html.ini b/tests/wpt/metadata/resource-timing/resource_redirects.html.ini
new file mode 100644
index 00000000000..c97b716ce5c
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_redirects.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_reparenting.html.ini b/tests/wpt/metadata/resource-timing/resource_reparenting.html.ini
new file mode 100644
index 00000000000..999306ca8ff
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_reparenting.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_script_types.html.ini b/tests/wpt/metadata/resource-timing/resource_script_types.html.ini
new file mode 100644
index 00000000000..984ebdc1d99
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_script_types.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_subframe_self_navigation.html.ini b/tests/wpt/metadata/resource-timing/resource_subframe_self_navigation.html.ini
new file mode 100644
index 00000000000..e96e303017d
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_subframe_self_navigation.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_timing.worker.js.ini b/tests/wpt/metadata/resource-timing/resource_timing.worker.js.ini
new file mode 100644
index 00000000000..a6c5cb163da
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_timing.worker.js.ini
@@ -0,0 +1,4 @@
+[resource_timing.worker.html]
+ [Performance Resouce Entries in workers]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/resource-timing/resource_timing_TAO_cross_origin_redirect.html.ini b/tests/wpt/metadata/resource-timing/resource_timing_TAO_cross_origin_redirect.html.ini
new file mode 100644
index 00000000000..3ce32f0f969
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_timing_TAO_cross_origin_redirect.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_timing_buffer_full_eventually.html.ini b/tests/wpt/metadata/resource-timing/resource_timing_buffer_full_eventually.html.ini
new file mode 100644
index 00000000000..aa1d99e9604
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_timing_buffer_full_eventually.html.ini
@@ -0,0 +1,5 @@
+[resource_timing_buffer_full_eventually.html]
+ expected: TIMEOUT
+ [Finite resource timing entries buffer size]
+ expected: TIMEOUT
+
diff --git a/tests/wpt/metadata/resource-timing/resource_timing_buffer_full_when_populate_entries.html.ini b/tests/wpt/metadata/resource-timing/resource_timing_buffer_full_when_populate_entries.html.ini
new file mode 100644
index 00000000000..4a3bb388608
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_timing_buffer_full_when_populate_entries.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_timing_buffer_full_when_shrink_buffer_size.html.ini b/tests/wpt/metadata/resource-timing/resource_timing_buffer_full_when_shrink_buffer_size.html.ini
new file mode 100644
index 00000000000..a1c46103452
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_timing_buffer_full_when_shrink_buffer_size.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_timing_cross_origin_redirect.html.ini b/tests/wpt/metadata/resource-timing/resource_timing_cross_origin_redirect.html.ini
new file mode 100644
index 00000000000..dbb2eb922f6
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_timing_cross_origin_redirect.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_timing_cross_origin_redirect_chain.html.ini b/tests/wpt/metadata/resource-timing/resource_timing_cross_origin_redirect_chain.html.ini
new file mode 100644
index 00000000000..b318d55200b
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_timing_cross_origin_redirect_chain.html.ini
@@ -0,0 +1,5 @@
+[resource_timing_cross_origin_redirect_chain.html]
+ expected: ERROR
+ [There should be one entry.]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/resource-timing/resource_timing_same_origin_redirect.html.ini b/tests/wpt/metadata/resource-timing/resource_timing_same_origin_redirect.html.ini
new file mode 100644
index 00000000000..8e839b27927
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_timing_same_origin_redirect.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/resource_timing_store_and_clear_during_callback.html.ini b/tests/wpt/metadata/resource-timing/resource_timing_store_and_clear_during_callback.html.ini
new file mode 100644
index 00000000000..8b7929d6ddc
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/resource_timing_store_and_clear_during_callback.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/resource-timing/single-entry-per-resource.html.ini b/tests/wpt/metadata/resource-timing/single-entry-per-resource.html.ini
new file mode 100644
index 00000000000..485e42b1d78
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/single-entry-per-resource.html.ini
@@ -0,0 +1,7 @@
+[single-entry-per-resource.html]
+ [One resource when reusing data]
+ expected: FAIL
+
+ [Only one resource entry per resource]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/resource-timing/test_resource_timing.html.ini b/tests/wpt/metadata/resource-timing/test_resource_timing.html.ini
new file mode 100644
index 00000000000..e52d422b64d
--- /dev/null
+++ b/tests/wpt/metadata/resource-timing/test_resource_timing.html.ini
@@ -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
+
diff --git a/tests/wpt/metadata/workers/baseurl/alpha/import-in-moduleworker.html.ini b/tests/wpt/metadata/workers/baseurl/alpha/import-in-moduleworker.html.ini
deleted file mode 100644
index bf2a1d61bab..00000000000
--- a/tests/wpt/metadata/workers/baseurl/alpha/import-in-moduleworker.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[import-in-moduleworker.html]
- [Base URL in module dedicated workers: import]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/workers/baseurl/alpha/sharedworker-in-worker.html.ini b/tests/wpt/metadata/workers/baseurl/alpha/sharedworker-in-worker.html.ini
deleted file mode 100644
index 333edb3a26e..00000000000
--- a/tests/wpt/metadata/workers/baseurl/alpha/sharedworker-in-worker.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[sharedworker-in-worker.html]
- [Base URL in workers: new SharedWorker()]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/workers/semantics/multiple-workers/005.html.ini b/tests/wpt/metadata/workers/semantics/multiple-workers/005.html.ini
deleted file mode 100644
index 9d72f08e38e..00000000000
--- a/tests/wpt/metadata/workers/semantics/multiple-workers/005.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[005.html]
- type: testharness
- [dedicated worker in shared worker in dedicated worker]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/workers/worker-performance.worker.js.ini b/tests/wpt/metadata/workers/worker-performance.worker.js.ini
index 49f33b3ec9a..6048b1478b2 100644
--- a/tests/wpt/metadata/workers/worker-performance.worker.js.ini
+++ b/tests/wpt/metadata/workers/worker-performance.worker.js.ini
@@ -1,3 +1,26 @@
[worker-performance.worker.html]
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
+
diff --git a/tests/wpt/metadata/xhr/sync-no-timeout.any.js.ini b/tests/wpt/metadata/xhr/sync-no-timeout.any.js.ini
index 842f7f5f93f..ecff1270f56 100644
--- a/tests/wpt/metadata/xhr/sync-no-timeout.any.js.ini
+++ b/tests/wpt/metadata/xhr/sync-no-timeout.any.js.ini
@@ -5,7 +5,3 @@
[sync-no-timeout]
expected: FAIL
-
-[sync-no-timeout.any.worker.html]
-
-[sync-no-timeout.any.html]
diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json
index d29df9db9e8..6cdd649c457 100644
--- a/tests/wpt/mozilla/meta/MANIFEST.json
+++ b/tests/wpt/mozilla/meta/MANIFEST.json
@@ -27064,7 +27064,7 @@
"testharness"
],
"mozilla/interfaces.html": [
- "b1de57409ad5e6f9fedeb8a34c9474b4e378ec0a",
+ "ad17e930ddb5bc2daecb86216efe8885ae399173",
"testharness"
],
"mozilla/interfaces.js": [
@@ -27072,7 +27072,7 @@
"support"
],
"mozilla/interfaces.worker.js": [
- "fbd6e92c097dea4f99924de219c9f6aa07a45282",
+ "a5f2e00f234ea66b80e8a9bd4dbbc5433926191f",
"testharness"
],
"mozilla/invalid-this.html": [
@@ -32904,11 +32904,11 @@
"testharness"
],
"mozilla/window_performance.html": [
- "6b96c18b3cdef8b8bce294f1b45ce09192b00cd0",
+ "690870b7080e179481ca0255f7c30337e8b6636a",
"testharness"
],
"mozilla/window_performance_topLevelDomComplete.html": [
- "ce2431a7279e7cefa9e8032edabe276ac5deb227",
+ "50bbc2917b5ac900b5061a0b2c30b6c1fef1067e",
"testharness"
],
"mozilla/window_requestAnimationFrame.html": [
diff --git a/tests/wpt/mozilla/meta/mozilla/window_performance.html.ini b/tests/wpt/mozilla/meta/mozilla/window_performance.html.ini
new file mode 100644
index 00000000000..9719867b4dc
--- /dev/null
+++ b/tests/wpt/mozilla/meta/mozilla/window_performance.html.ini
@@ -0,0 +1,4 @@
+[window_performance.html]
+ [window_performance]
+ expected: FAIL
+
diff --git a/tests/wpt/mozilla/tests/mozilla/interfaces.html b/tests/wpt/mozilla/tests/mozilla/interfaces.html
index b1de57409ad..ad17e930ddb 100644
--- a/tests/wpt/mozilla/tests/mozilla/interfaces.html
+++ b/tests/wpt/mozilla/tests/mozilla/interfaces.html
@@ -181,10 +181,11 @@ test_interfaces([
"PerformanceEntry",
"PerformanceMark",
"PerformanceMeasure",
+ "PerformanceNavigationTiming",
"PerformanceObserver",
"PerformanceObserverEntryList",
"PerformancePaintTiming",
- "PerformanceTiming",
+ "PerformanceResourceTiming",
"Plugin",
"PluginArray",
"PopStateEvent",
diff --git a/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js b/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js
index fbd6e92c097..a5f2e00f234 100644
--- a/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js
+++ b/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js
@@ -39,6 +39,7 @@ test_interfaces([
"PerformanceObserver",
"PerformanceObserverEntryList",
"PerformancePaintTiming",
+ "PerformanceResourceTiming",
"ProgressEvent",
"PromiseRejectionEvent",
"Request",
diff --git a/tests/wpt/mozilla/tests/mozilla/window_performance.html b/tests/wpt/mozilla/tests/mozilla/window_performance.html
index 6b96c18b3cd..690870b7080 100644
--- a/tests/wpt/mozilla/tests/mozilla/window_performance.html
+++ b/tests/wpt/mozilla/tests/mozilla/window_performance.html
@@ -11,9 +11,13 @@ test(function() {
assert_true(window.performance instanceof Performance, "Should be Performance");
assert_not_equals(window.performance.timing, undefined);
- assert_true(window.performance.timing instanceof PerformanceTiming, "Should be PerformanceTiming");
- assert_greater_than(window.performance.timing.navigationStart, 0);
+ var entries = window.performance.getEntries();
+ assert_not_equals(entries.length, 0);
+ assert_true(entries[0] instanceof PerformanceNavigationTiming);
+
+ // TODO(#21254) navigationTiming/startTime is not fully implemented yet, so this assertion will fail
+ assert_greater_than(entries[0].startTime, 0);
var last = window.performance.now();
assert_greater_than(last, 0);
diff --git a/tests/wpt/mozilla/tests/mozilla/window_performance_topLevelDomComplete.html b/tests/wpt/mozilla/tests/mozilla/window_performance_topLevelDomComplete.html
index ce2431a7279..50bbc2917b5 100644
--- a/tests/wpt/mozilla/tests/mozilla/window_performance_topLevelDomComplete.html
+++ b/tests/wpt/mozilla/tests/mozilla/window_performance_topLevelDomComplete.html
@@ -1,18 +1,23 @@
-<html>
-<head>
- <title>Performance toLevelDomComplete</title>
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
-</head>
+<!doctype html>
+<meta charset="utf-8">
+<title>Performance topLevelDomComplete</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
<body>
<script>
-async_test(function(t) {
- window.onload = t.step_func(function() {
- assert_true(performance.timing.domLoading <= performance.timing.topLevelDomComplete);
- assert_true(performance.timing.topLevelDomComplete <= performance.timing.domComplete);
- t.done();
- });
-}, "performance.topLevelDomComplete");
+async_test(function (t) {
+ window.onload = t.step_func(function (entryList, obs) {
+ var entries = window.performance.getEntries();
+ assert_greater_than(entries.length, 0);
+ var navigation = entries[0];
+ assert_true(navigation instanceof PerformanceNavigationTiming);
+
+ assert_true(navigation.domContentLoadedEventStart <= navigation.topLevelDomComplete);
+ assert_true(navigation.topLevelDomComplete <= navigation.domComplete);
+
+ t.done();
+ });
+}, "top level dom complete");
</script>
</body>
-</html>
+