mirror of
https://github.com/servo/servo
synced 2026-04-25 17:15:48 +02:00
Compare commits
2 Commits
f9cfd05af8
...
tmp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c95609dece | ||
|
|
9f6656d83b |
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1952,6 +1952,7 @@ dependencies = [
|
||||
"servo_arc 0.1.1",
|
||||
"servo_config 0.0.1",
|
||||
"servo_url 0.0.1",
|
||||
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender_api 0.57.2 (git+https://github.com/servo/webrender)",
|
||||
|
||||
@@ -17,7 +17,7 @@ use hyper::mime::{Mime, SubLevel, TopLevel};
|
||||
use hyper::status::StatusCode;
|
||||
use ipc_channel::ipc::IpcReceiver;
|
||||
use mime_guess::guess_mime_type;
|
||||
use net_traits::{FetchTaskTarget, NetworkError, ReferrerPolicy};
|
||||
use net_traits::{FetchTaskTarget, NetworkError, ReferrerPolicy, ResourceFetchTiming};
|
||||
use net_traits::request::{CredentialsMode, Destination, Referrer, Request, RequestMode};
|
||||
use net_traits::request::{ResponseTainting, Origin, Window};
|
||||
use net_traits::response::{Response, ResponseBody, ResponseType};
|
||||
@@ -82,14 +82,14 @@ pub type DoneChannel = Option<(Sender<Data>, Receiver<Data>)>;
|
||||
/// [Fetch](https://fetch.spec.whatwg.org#concept-fetch)
|
||||
pub fn fetch(request: &mut Request,
|
||||
target: Target,
|
||||
context: &FetchContext) {
|
||||
context: &mut FetchContext) {
|
||||
fetch_with_cors_cache(request, &mut CorsCache::new(), target, context);
|
||||
}
|
||||
|
||||
pub fn fetch_with_cors_cache(request: &mut Request,
|
||||
cache: &mut CorsCache,
|
||||
target: Target,
|
||||
context: &FetchContext) {
|
||||
context: &mut FetchContext) {
|
||||
// Step 1.
|
||||
if request.window == Window::Client {
|
||||
// TODO: Set window to request's client object if client is a Window object
|
||||
@@ -121,7 +121,7 @@ pub fn fetch_with_cors_cache(request: &mut Request,
|
||||
}
|
||||
|
||||
// Step 8.
|
||||
main_fetch(request, cache, false, false, target, &mut None, &context);
|
||||
main_fetch(request, cache, false, false, target, &mut None, context);
|
||||
}
|
||||
|
||||
/// [Main fetch](https://fetch.spec.whatwg.org/#concept-main-fetch)
|
||||
@@ -131,7 +131,7 @@ pub fn main_fetch(request: &mut Request,
|
||||
recursive_flag: bool,
|
||||
target: Target,
|
||||
done_chan: &mut DoneChannel,
|
||||
context: &FetchContext)
|
||||
context: &mut FetchContext)
|
||||
-> Response {
|
||||
// Step 1.
|
||||
let mut response = None;
|
||||
@@ -452,13 +452,13 @@ fn scheme_fetch(request: &mut Request,
|
||||
cache: &mut CorsCache,
|
||||
target: Target,
|
||||
done_chan: &mut DoneChannel,
|
||||
context: &FetchContext)
|
||||
context: &mut FetchContext)
|
||||
-> Response {
|
||||
let url = request.current_url();
|
||||
|
||||
match url.scheme() {
|
||||
"about" if url.path() == "blank" => {
|
||||
let mut response = Response::new(url);
|
||||
let mut response = Response::new(url, ResourceFetchTiming::new());
|
||||
response.headers.set(ContentType(mime!(Text / Html; Charset = Utf8)));
|
||||
*response.body.lock().unwrap() = ResponseBody::Done(vec![]);
|
||||
response
|
||||
@@ -471,7 +471,7 @@ fn scheme_fetch(request: &mut Request,
|
||||
"data" => {
|
||||
match decode(&url) {
|
||||
Ok((mime, bytes)) => {
|
||||
let mut response = Response::new(url);
|
||||
let mut response = Response::new(url, ResourceFetchTiming::new());
|
||||
*response.body.lock().unwrap() = ResponseBody::Done(bytes);
|
||||
response.headers.set(ContentType(mime));
|
||||
response
|
||||
@@ -490,7 +490,7 @@ fn scheme_fetch(request: &mut Request,
|
||||
let _ = file.read_to_end(&mut bytes);
|
||||
let mime = guess_mime_type(file_path);
|
||||
|
||||
let mut response = Response::new(url);
|
||||
let mut response = Response::new(url, ResourceFetchTiming::new());
|
||||
*response.body.lock().unwrap() = ResponseBody::Done(bytes);
|
||||
response.headers.set(ContentType(mime));
|
||||
response
|
||||
@@ -514,7 +514,7 @@ fn scheme_fetch(request: &mut Request,
|
||||
|
||||
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());
|
||||
response.headers = headers;
|
||||
*response.body.lock().unwrap() = ResponseBody::Done(bytes);
|
||||
response
|
||||
|
||||
@@ -16,7 +16,7 @@ use hyper::status::StatusCode;
|
||||
use hyper_serde::Serde;
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps, MallocUnconditionalSizeOf, MallocUnconditionalShallowSizeOf};
|
||||
use malloc_size_of::Measurable;
|
||||
use net_traits::{Metadata, FetchMetadata};
|
||||
use net_traits::{Metadata, FetchMetadata, ResourceFetchTiming};
|
||||
use net_traits::request::Request;
|
||||
use net_traits::response::{HttpsState, Response, ResponseBody};
|
||||
use servo_arc::Arc;
|
||||
@@ -311,7 +311,8 @@ fn create_cached_response(request: &Request,
|
||||
cached_headers: &Headers,
|
||||
done_chan: &mut DoneChannel)
|
||||
-> CachedResponse {
|
||||
let mut response = Response::new(cached_resource.data.metadata.data.final_url.clone());
|
||||
let resource_timing = ResourceFetchTiming::new();
|
||||
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() {
|
||||
@@ -644,7 +645,9 @@ 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();
|
||||
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();
|
||||
@@ -704,8 +707,8 @@ impl HttpCache {
|
||||
let metadata = match response.metadata() {
|
||||
Ok(FetchMetadata::Filtered {
|
||||
filtered: _,
|
||||
unsafe_: metadata }) |
|
||||
Ok(FetchMetadata::Unfiltered(metadata)) => metadata,
|
||||
unsafe_: m }) |
|
||||
Ok(FetchMetadata::Unfiltered(m)) => m,
|
||||
_ => return,
|
||||
};
|
||||
if !response_is_cacheable(&metadata) {
|
||||
|
||||
@@ -34,6 +34,7 @@ use hyper_serde::Serde;
|
||||
use log;
|
||||
use msg::constellation_msg::{HistoryStateId, PipelineId};
|
||||
use net_traits::{CookieSource, FetchMetadata, NetworkError, ReferrerPolicy};
|
||||
use net_traits::{ResourceFetchTiming, ResourceAttribute};
|
||||
use net_traits::request::{CacheMode, CredentialsMode, Destination, Origin};
|
||||
use net_traits::request::{RedirectMode, Referrer, Request, RequestMode};
|
||||
use net_traits::request::{ResponseTainting, ServiceWorkersMode};
|
||||
@@ -50,8 +51,7 @@ use std::str::FromStr;
|
||||
use std::sync::RwLock;
|
||||
use std::sync::mpsc::{channel, Sender};
|
||||
use std::thread;
|
||||
use time;
|
||||
use time::Tm;
|
||||
use time::{self, Tm};
|
||||
use unicase::UniCase;
|
||||
use uuid;
|
||||
|
||||
@@ -381,7 +381,8 @@ fn obtain_response(connector: &Pool<Connector>,
|
||||
iters: u32,
|
||||
request_id: Option<&str>,
|
||||
is_xhr: bool)
|
||||
-> Result<(HyperResponse, Option<ChromeToDevtoolsControlMsg>), NetworkError> {
|
||||
-> Result<(HyperResponse, Option<ChromeToDevtoolsControlMsg>),
|
||||
NetworkError> {
|
||||
let null_data = None;
|
||||
|
||||
// loop trying connections in connection pool
|
||||
@@ -420,6 +421,8 @@ fn obtain_response(connector: &Pool<Connector>,
|
||||
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();
|
||||
|
||||
let request = HyperRequest::with_connector(method.clone(),
|
||||
@@ -431,6 +434,7 @@ fn obtain_response(connector: &Pool<Connector>,
|
||||
};
|
||||
*request.headers_mut() = headers.clone();
|
||||
|
||||
//TODO(#21262) connect_end
|
||||
let connect_end = precise_time_ms();
|
||||
|
||||
let send_start = precise_time_ms();
|
||||
@@ -446,6 +450,7 @@ fn obtain_response(connector: &Pool<Connector>,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(#21271) response_start: immediately after receiving first byte of response
|
||||
let response = match request_writer.send() {
|
||||
Ok(w) => w,
|
||||
Err(HttpError::Io(ref io_error))
|
||||
@@ -457,6 +462,8 @@ fn obtain_response(connector: &Pool<Connector>,
|
||||
Err(e) => return Err(NetworkError::Internal(e.description().to_owned())),
|
||||
};
|
||||
|
||||
// TODO(#21263) response_end (also needs to be set above if fetch is aborted due to an error)
|
||||
|
||||
let send_end = precise_time_ms();
|
||||
|
||||
let msg = if let Some(request_id) = request_id {
|
||||
@@ -486,12 +493,13 @@ pub fn http_fetch(request: &mut Request,
|
||||
authentication_fetch_flag: bool,
|
||||
target: Target,
|
||||
done_chan: &mut DoneChannel,
|
||||
context: &FetchContext)
|
||||
context: &mut FetchContext)
|
||||
-> Response {
|
||||
// This is a new async fetch, reset the channel we are waiting on
|
||||
*done_chan = None;
|
||||
// Step 1
|
||||
let mut response: Option<Response> = None;
|
||||
let mut resource_timing = ResourceFetchTiming::new();
|
||||
|
||||
// Step 2
|
||||
// nothing to do, since actual_response is a function on response
|
||||
@@ -563,8 +571,17 @@ pub fn http_fetch(request: &mut Request,
|
||||
}
|
||||
|
||||
// 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)
|
||||
resource_timing.set_attribute(ResourceAttribute::RequestStart);
|
||||
|
||||
let mut fetch_result = http_network_or_cache_fetch(
|
||||
request, authentication_fetch_flag, cors_flag, done_chan, context);
|
||||
request, authentication_fetch_flag, cors_flag, done_chan, context, &mut resource_timing);
|
||||
|
||||
// Substep 4
|
||||
if cors_flag && cors_check(&request, &fetch_result).is_err() {
|
||||
@@ -607,8 +624,15 @@ pub fn http_fetch(request: &mut Request,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// TODO redirect_end: last byte of response of last redirect
|
||||
|
||||
// set back to default
|
||||
response.return_internal = true;
|
||||
resource_timing.set_attribute(ResourceAttribute::RedirectCount(request.redirect_count as u16));
|
||||
|
||||
*response.get_resource_timing_mut() = resource_timing;
|
||||
|
||||
// Step 6
|
||||
response
|
||||
}
|
||||
@@ -620,7 +644,7 @@ pub fn http_redirect_fetch(request: &mut Request,
|
||||
cors_flag: bool,
|
||||
target: Target,
|
||||
done_chan: &mut DoneChannel,
|
||||
context: &FetchContext)
|
||||
context: &mut FetchContext)
|
||||
-> Response {
|
||||
// Step 1
|
||||
assert!(response.return_internal);
|
||||
@@ -713,7 +737,8 @@ fn http_network_or_cache_fetch(request: &mut Request,
|
||||
authentication_fetch_flag: bool,
|
||||
cors_flag: bool,
|
||||
done_chan: &mut DoneChannel,
|
||||
context: &FetchContext)
|
||||
context: &mut FetchContext,
|
||||
mut resource_timing: &mut ResourceFetchTiming)
|
||||
-> Response {
|
||||
// TODO: Implement Window enum for Request
|
||||
let request_has_no_window = true;
|
||||
@@ -942,7 +967,7 @@ fn http_network_or_cache_fetch(request: &mut Request,
|
||||
if response.is_none() {
|
||||
// Substep 2
|
||||
let forward_response = http_network_fetch(http_request, credentials_flag,
|
||||
done_chan, context);
|
||||
done_chan, context, &resource_timing);
|
||||
// Substep 3
|
||||
if let Some((200...399, _)) = forward_response.raw_status {
|
||||
if !http_request.method.safe() {
|
||||
@@ -998,7 +1023,8 @@ fn http_network_or_cache_fetch(request: &mut Request,
|
||||
// Substep 4
|
||||
response = http_network_or_cache_fetch(http_request,
|
||||
true /* authentication flag */,
|
||||
cors_flag, done_chan, context);
|
||||
cors_flag, done_chan, context,
|
||||
&mut resource_timing);
|
||||
}
|
||||
|
||||
// Step 24
|
||||
@@ -1037,7 +1063,8 @@ fn http_network_or_cache_fetch(request: &mut Request,
|
||||
fn http_network_fetch(request: &Request,
|
||||
credentials_flag: bool,
|
||||
done_chan: &mut DoneChannel,
|
||||
context: &FetchContext)
|
||||
context: &mut FetchContext,
|
||||
resource_timing: &ResourceFetchTiming)
|
||||
-> Response {
|
||||
// Step 1
|
||||
// nothing to do here, since credentials_flag is already a boolean
|
||||
@@ -1083,7 +1110,7 @@ fn http_network_fetch(request: &Request,
|
||||
}
|
||||
}
|
||||
|
||||
let mut response = Response::new(url.clone());
|
||||
let mut response = Response::new(url.clone(), resource_timing.to_owned());
|
||||
response.status = Some(res.status);
|
||||
response.raw_status = Some((res.status_raw().0,
|
||||
res.status_raw().1.as_bytes().to_vec()));
|
||||
@@ -1100,6 +1127,7 @@ fn http_network_fetch(request: &Request,
|
||||
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();
|
||||
@@ -1224,7 +1252,7 @@ fn http_network_fetch(request: &Request,
|
||||
/// [CORS preflight fetch](https://fetch.spec.whatwg.org#cors-preflight-fetch)
|
||||
fn cors_preflight_fetch(request: &Request,
|
||||
cache: &mut CorsCache,
|
||||
context: &FetchContext)
|
||||
context: &mut FetchContext)
|
||||
-> Response {
|
||||
// Step 1
|
||||
let mut preflight = Request::new(request.current_url(), Some(request.origin.clone()), request.pipeline_id);
|
||||
@@ -1253,7 +1281,8 @@ fn cors_preflight_fetch(request: &Request,
|
||||
}
|
||||
|
||||
// Step 5
|
||||
let response = http_network_or_cache_fetch(&mut preflight, false, false, &mut None, context);
|
||||
let mut resource_timing = ResourceFetchTiming::new();
|
||||
let response = http_network_or_cache_fetch(&mut preflight, false, false, &mut None, context, &mut resource_timing);
|
||||
|
||||
// Step 6
|
||||
if cors_check(&request, &response).is_ok() &&
|
||||
|
||||
@@ -524,11 +524,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()
|
||||
};
|
||||
|
||||
@@ -67,7 +67,6 @@ pub fn new_resource_threads(user_agent: Cow<'static, str>,
|
||||
ResourceThreads::new(private_core, storage))
|
||||
}
|
||||
|
||||
|
||||
/// Create a CoreResourceThread
|
||||
pub fn new_core_resource_thread(user_agent: Cow<'static, str>,
|
||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||
@@ -413,7 +412,7 @@ impl CoreResourceManager {
|
||||
// todo load context / mimesniff in fetch
|
||||
// todo referrer policy?
|
||||
// todo service worker stuff
|
||||
let context = FetchContext {
|
||||
let mut context = FetchContext {
|
||||
state: http_state,
|
||||
user_agent: ua,
|
||||
devtools_chan: dc,
|
||||
@@ -430,9 +429,9 @@ impl CoreResourceManager {
|
||||
true,
|
||||
&mut sender,
|
||||
&mut None,
|
||||
&context);
|
||||
&mut context);
|
||||
},
|
||||
None => fetch(&mut request, &mut sender, &context),
|
||||
None => fetch(&mut request, &mut sender, &mut context),
|
||||
};
|
||||
}).expect("Thread spawning failed");
|
||||
}
|
||||
|
||||
@@ -118,7 +118,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 {
|
||||
@@ -137,7 +137,7 @@ fn test_fetch_blob() {
|
||||
|
||||
|
||||
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());
|
||||
|
||||
@@ -535,7 +535,7 @@ fn test_fetch_with_hsts() {
|
||||
File::open(cert_path).unwrap().read_to_string(&mut ca_content).unwrap();
|
||||
let ssl_client = create_ssl_client(&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,
|
||||
@@ -555,7 +555,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);
|
||||
let _ = server.close();
|
||||
assert_eq!(response.internal_response.unwrap().url().unwrap().scheme(),
|
||||
"https");
|
||||
|
||||
@@ -504,8 +504,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();
|
||||
|
||||
@@ -521,7 +521,7 @@ fn test_load_sets_cookies_in_the_resource_manager_when_it_get_set_cookie_header_
|
||||
};
|
||||
let (mut 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);
|
||||
|
||||
@@ -535,7 +535,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();
|
||||
|
||||
@@ -553,7 +553,7 @@ fn test_load_sets_requests_cookies_header_for_url_by_getting_cookies_from_the_re
|
||||
};
|
||||
let (mut 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();
|
||||
@@ -575,7 +575,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();
|
||||
|
||||
@@ -591,7 +591,7 @@ fn test_load_sends_cookie_if_nonhttp() {
|
||||
};
|
||||
let (mut 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();
|
||||
@@ -613,7 +613,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();
|
||||
|
||||
@@ -629,7 +629,7 @@ fn test_cookie_set_with_httponly_should_not_be_available_using_getcookiesforurl(
|
||||
};
|
||||
let (mut 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);
|
||||
|
||||
@@ -643,7 +643,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();
|
||||
|
||||
@@ -663,7 +663,7 @@ fn test_when_cookie_received_marked_secure_is_ignored_for_http() {
|
||||
};
|
||||
let (mut 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);
|
||||
|
||||
@@ -677,7 +677,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();
|
||||
|
||||
@@ -981,7 +981,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(
|
||||
@@ -1009,7 +1009,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();
|
||||
|
||||
@@ -1085,7 +1085,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(),
|
||||
@@ -1094,7 +1094,7 @@ fn test_if_auth_creds_not_in_url_but_in_cache_it_sets_it() {
|
||||
|
||||
context.state.auth_cache.write().unwrap().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();
|
||||
|
||||
|
||||
@@ -105,16 +105,16 @@ 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) = channel();
|
||||
let mut target = FetchResponseCollector {
|
||||
sender: sender,
|
||||
};
|
||||
|
||||
methods::fetch(request, &mut target, context);
|
||||
methods::fetch(request, &mut target, &mut context);
|
||||
|
||||
receiver.recv().unwrap()
|
||||
}
|
||||
@@ -125,7 +125,7 @@ fn fetch_with_cors_cache(request: &mut Request, cache: &mut CorsCache) -> Respon
|
||||
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()
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
use net::subresource_integrity::{SriEntry, get_prioritized_hash_function, get_strongest_metadata};
|
||||
use net::subresource_integrity::{is_response_integrity_valid, parsed_metadata};
|
||||
use net_traits::ResourceFetchTiming;
|
||||
use net_traits::response::{Response, ResponseBody};
|
||||
use servo_url::ServoUrl;
|
||||
|
||||
@@ -70,7 +71,7 @@ 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());
|
||||
|
||||
let integrity_metadata = "sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO";
|
||||
let response_body = "alert('Hello, world.');".to_owned().into_bytes();
|
||||
@@ -82,7 +83,7 @@ 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());
|
||||
|
||||
let integrity_metadata = "sha256-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO";
|
||||
let response_body = "alert('Hello, world.');".to_owned().into_bytes();
|
||||
|
||||
@@ -28,6 +28,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.6", features = ["v4", "serde"]}
|
||||
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
|
||||
|
||||
@@ -20,6 +20,7 @@ extern crate num_traits;
|
||||
#[macro_use] extern crate serde;
|
||||
extern crate servo_arc;
|
||||
extern crate servo_url;
|
||||
extern crate time;
|
||||
extern crate url;
|
||||
extern crate uuid;
|
||||
extern crate webrender_api;
|
||||
@@ -40,6 +41,7 @@ use response::{HttpsState, Response, ResponseInit};
|
||||
use servo_url::ServoUrl;
|
||||
use std::error::Error;
|
||||
use storage_thread::StorageThreadMsg;
|
||||
use time::precise_time_ns;
|
||||
|
||||
pub mod blob_url_store;
|
||||
pub mod filemanager_thread;
|
||||
@@ -156,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,6 +209,9 @@ pub trait FetchResponseListener {
|
||||
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 resource_timing(&self) -> &ResourceFetchTiming;
|
||||
fn resource_timing_mut(&mut self) -> &mut ResourceFetchTiming;
|
||||
fn submit_resource_timing(&mut self);
|
||||
}
|
||||
|
||||
impl FetchTaskTarget for IpcSender<FetchResponseMsg> {
|
||||
@@ -230,7 +235,7 @@ 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 +253,22 @@ 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) => {
|
||||
*listener.resource_timing_mut() = response_resource_timing.clone();
|
||||
listener.process_response_eof(Ok(()));
|
||||
// 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)),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -400,6 +420,45 @@ pub struct ResourceCorsData {
|
||||
pub origin: ServoUrl,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
|
||||
pub struct ResourceFetchTiming {
|
||||
/// 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,
|
||||
}
|
||||
|
||||
impl ResourceFetchTiming {
|
||||
pub fn new() -> ResourceFetchTiming {
|
||||
ResourceFetchTiming {
|
||||
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, Deserialize, MallocSizeOf, Serialize)]
|
||||
pub struct Metadata {
|
||||
@@ -499,7 +558,8 @@ pub fn load_whole_resource(request: RequestInit,
|
||||
})
|
||||
},
|
||||
FetchResponseMsg::ProcessResponseChunk(data) => buf.extend_from_slice(&data),
|
||||
FetchResponseMsg::ProcessResponseEOF(Ok(())) => return Ok((metadata.unwrap(), buf)),
|
||||
//TODO return timing information
|
||||
FetchResponseMsg::ProcessResponseEOF(Ok(_)) => return Ok((metadata.unwrap(), buf)),
|
||||
FetchResponseMsg::ProcessResponse(Err(e)) |
|
||||
FetchResponseMsg::ProcessResponseEOF(Err(e)) => return Err(e),
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
//! The [Response](https://fetch.spec.whatwg.org/#responses) object
|
||||
//! resulting from a [fetch operation](https://fetch.spec.whatwg.org/#concept-fetch)
|
||||
use {FetchMetadata, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy};
|
||||
use {FetchMetadata, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy, ResourceFetchTiming};
|
||||
use hyper::header::{AccessControlExposeHeaders, ContentType, Headers};
|
||||
use hyper::status::StatusCode;
|
||||
use hyper_serde::Serde;
|
||||
@@ -117,10 +117,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
|
||||
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,
|
||||
@@ -139,11 +141,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);
|
||||
let mut res = Response::new(init.url, ResourceFetchTiming::new());
|
||||
res.location_url = init.location_url;
|
||||
res.headers = init.headers;
|
||||
res.referrer = init.referrer;
|
||||
@@ -169,6 +172,7 @@ impl Response {
|
||||
internal_response: None,
|
||||
return_internal: true,
|
||||
aborted: Arc::new(AtomicBool::new(false)),
|
||||
resource_timing: ResourceFetchTiming::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,6 +218,14 @@ impl Response {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_resource_timing(&self) -> &ResourceFetchTiming {
|
||||
&self.resource_timing
|
||||
}
|
||||
|
||||
pub fn get_resource_timing_mut(&mut self) -> &mut ResourceFetchTiming {
|
||||
&mut 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)]
|
||||
@@ -318,22 +330,22 @@ impl Response {
|
||||
match self.response_type {
|
||||
ResponseType::Basic => Ok(FetchMetadata::Filtered {
|
||||
filtered: FilteredMetadata::Basic(metadata.unwrap()),
|
||||
unsafe_: unsafe_metadata
|
||||
unsafe_: unsafe_metadata,
|
||||
}),
|
||||
ResponseType::Cors => Ok(FetchMetadata::Filtered {
|
||||
filtered: FilteredMetadata::Cors(metadata.unwrap()),
|
||||
unsafe_: unsafe_metadata
|
||||
unsafe_: unsafe_metadata,
|
||||
}),
|
||||
ResponseType::Default => unreachable!(),
|
||||
ResponseType::Error(ref network_err) =>
|
||||
Err(network_err.clone()),
|
||||
ResponseType::Opaque => Ok(FetchMetadata::Filtered {
|
||||
filtered: FilteredMetadata::Opaque,
|
||||
unsafe_: unsafe_metadata
|
||||
unsafe_: unsafe_metadata,
|
||||
}),
|
||||
ResponseType::OpaqueRedirect => Ok(FetchMetadata::Filtered {
|
||||
filtered: FilteredMetadata::OpaqueRedirect,
|
||||
unsafe_: unsafe_metadata
|
||||
unsafe_: unsafe_metadata,
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
@@ -31,22 +31,35 @@ fn main() {
|
||||
build.generator("Ninja");
|
||||
// because we're using ninja, we need to explicitly set these
|
||||
// to VC++, otherwise it'll try to use cc
|
||||
build.define("CMAKE_C_COMPILER", "cl.exe")
|
||||
.define("CMAKE_CXX_COMPILER", "cl.exe");
|
||||
build.define("CMAKE_C_COMPILER", "cl.exe").define(
|
||||
"CMAKE_CXX_COMPILER",
|
||||
"cl.exe",
|
||||
);
|
||||
// We have to explicitly specify the full path to link.exe,
|
||||
// for reasons that I don't understand. If we just give
|
||||
// link.exe, it tries to use script-*/out/link.exe, which of
|
||||
// course does not exist.
|
||||
let link = std::process::Command::new("where").arg("link.exe").output().unwrap();
|
||||
let link_path: Vec<&str> = std::str::from_utf8(&link.stdout).unwrap().split("\r\n").collect();
|
||||
let link = std::process::Command::new("where")
|
||||
.arg("link.exe")
|
||||
.output()
|
||||
.unwrap();
|
||||
let link_path: Vec<&str> = std::str::from_utf8(&link.stdout)
|
||||
.unwrap()
|
||||
.split("\r\n")
|
||||
.collect();
|
||||
build.define("CMAKE_LINKER", link_path[0]);
|
||||
}
|
||||
|
||||
build.build();
|
||||
|
||||
println!("Binding generation completed in {}s", start.elapsed().as_secs());
|
||||
println!(
|
||||
"Binding generation completed in {}s",
|
||||
start.elapsed().as_secs()
|
||||
);
|
||||
|
||||
let json = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("build").join("InterfaceObjectMapData.json");
|
||||
let json = PathBuf::from(env::var_os("OUT_DIR").unwrap())
|
||||
.join("build")
|
||||
.join("InterfaceObjectMapData.json");
|
||||
let json: Value = serde_json::from_reader(File::open(&json).unwrap()).unwrap();
|
||||
let mut map = phf_codegen::Map::new();
|
||||
for (key, value) in json.as_object().unwrap() {
|
||||
@@ -54,7 +67,10 @@ fn main() {
|
||||
}
|
||||
let phf = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("InterfaceObjectMapPhf.rs");
|
||||
let mut phf = File::create(&phf).unwrap();
|
||||
write!(&mut phf, "pub static MAP: phf::Map<&'static [u8], unsafe fn(*mut JSContext, HandleObject)> = ").unwrap();
|
||||
write!(
|
||||
&mut phf,
|
||||
"pub static MAP: phf::Map<&'static [u8], unsafe fn(*mut JSContext, HandleObject)> = "
|
||||
).unwrap();
|
||||
map.build(&mut phf).unwrap();
|
||||
write!(&mut phf, ";\n").unwrap();
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ use dom::bindings::str::{DOMString, USVString};
|
||||
use dom::bindings::utils::WindowProxyHandler;
|
||||
use dom::document::PendingRestyle;
|
||||
use dom::htmlimageelement::SourceSet;
|
||||
use dom::performanceresourcetiming::InitiatorType;
|
||||
use encoding_rs::{Decoder, Encoding};
|
||||
use euclid::{Transform2D, Transform3D, Point2D, Vector2D, Rect, TypedSize2D, TypedScale};
|
||||
use euclid::Length as EuclidLength;
|
||||
@@ -68,7 +69,7 @@ use js::typedarray::TypedArray;
|
||||
use js::typedarray::TypedArrayElement;
|
||||
use metrics::{InteractiveMetrics, InteractiveWindow};
|
||||
use msg::constellation_msg::{BrowsingContextId, HistoryStateId, PipelineId, TopLevelBrowsingContextId};
|
||||
use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceThreads};
|
||||
use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceFetchTiming, ResourceThreads};
|
||||
use net_traits::filemanager_thread::RelativePos;
|
||||
use net_traits::image::base::{Image, ImageMetadata};
|
||||
use net_traits::image_cache::{ImageCache, PendingImageId};
|
||||
@@ -429,6 +430,8 @@ unsafe_no_jsmanaged_fields!(InteractiveMetrics);
|
||||
unsafe_no_jsmanaged_fields!(InteractiveWindow);
|
||||
unsafe_no_jsmanaged_fields!(CanvasId);
|
||||
unsafe_no_jsmanaged_fields!(SourceSet);
|
||||
unsafe_no_jsmanaged_fields!(ResourceFetchTiming);
|
||||
unsafe_no_jsmanaged_fields!(InitiatorType);
|
||||
|
||||
unsafe impl<'a> JSTraceable for &'a str {
|
||||
#[inline]
|
||||
|
||||
@@ -344,6 +344,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.
|
||||
@@ -392,6 +394,7 @@ pub struct Document {
|
||||
salvageable: Cell<bool>,
|
||||
/// Whether the unload event has already been fired.
|
||||
fired_unload: Cell<bool>,
|
||||
redirect_count: Cell<u16>,
|
||||
}
|
||||
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
@@ -2134,6 +2137,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();
|
||||
@@ -2447,6 +2458,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,
|
||||
@@ -2465,7 +2478,8 @@ impl Document {
|
||||
throw_on_dynamic_markup_insertion_counter: Cell::new(0),
|
||||
page_showing: Cell::new(false),
|
||||
salvageable: Cell::new(true),
|
||||
fired_unload: Cell::new(false)
|
||||
fired_unload: Cell::new(false),
|
||||
redirect_count: Cell::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2525,9 +2539,18 @@ impl Document {
|
||||
let node = document.upcast::<Node>();
|
||||
node.set_owner_doc(&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>);
|
||||
@@ -3947,6 +3970,7 @@ impl DocumentMethods for Document {
|
||||
|
||||
// Step 10.
|
||||
// TODO: prompt to unload.
|
||||
// TODO: set unload_event_start and unload_event_end
|
||||
|
||||
window_from_node(self).set_navigation_start();
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ use dom::event::Event;
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::messageevent::MessageEvent;
|
||||
use dom::performanceresourcetiming::InitiatorType;
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::Length;
|
||||
use fetch::FetchCanceller;
|
||||
@@ -25,10 +26,10 @@ use js::jsapi::JSAutoCompartment;
|
||||
use js::jsval::UndefinedValue;
|
||||
use mime::{Mime, TopLevel, SubLevel};
|
||||
use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata};
|
||||
use net_traits::{FetchResponseMsg, FetchResponseListener, NetworkError};
|
||||
use net_traits::{FetchResponseMsg, FetchResponseListener, NetworkError, ResourceFetchTiming};
|
||||
use net_traits::request::{CacheMode, CorsSettings, CredentialsMode};
|
||||
use net_traits::request::{RequestInit, RequestMode};
|
||||
use network_listener::{NetworkListener, PreInvoke};
|
||||
use network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||
use servo_atoms::Atom;
|
||||
use servo_url::ServoUrl;
|
||||
use std::cell::Cell;
|
||||
@@ -90,6 +91,8 @@ struct EventSourceContext {
|
||||
event_type: String,
|
||||
data: String,
|
||||
last_event_id: String,
|
||||
|
||||
resource_timing: ResourceFetchTiming,
|
||||
}
|
||||
|
||||
impl EventSourceContext {
|
||||
@@ -380,6 +383,28 @@ impl FetchResponseListener for EventSourceContext {
|
||||
}
|
||||
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 {
|
||||
@@ -437,6 +462,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,
|
||||
url: DOMString,
|
||||
@@ -497,6 +526,7 @@ impl EventSource {
|
||||
event_type: String::new(),
|
||||
data: String::new(),
|
||||
last_event_id: String::new(),
|
||||
resource_timing: ResourceFetchTiming::new(),
|
||||
};
|
||||
let listener = NetworkListener {
|
||||
context: Arc::new(Mutex::new(context)),
|
||||
|
||||
@@ -26,6 +26,7 @@ use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
|
||||
use dom::element::{reflect_cross_origin_attribute, set_cross_origin_attribute};
|
||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::htmlareaelement::HTMLAreaElement;
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::htmlformelement::{FormControl, HTMLFormElement};
|
||||
@@ -34,6 +35,7 @@ use dom::htmlpictureelement::HTMLPictureElement;
|
||||
use dom::htmlsourceelement::HTMLSourceElement;
|
||||
use dom::mouseevent::MouseEvent;
|
||||
use dom::node::{Node, NodeDamage, document_from_node, window_from_node};
|
||||
use dom::performanceresourcetiming::InitiatorType;
|
||||
use dom::progressevent::ProgressEvent;
|
||||
use dom::values::UNSIGNED_LONG_MAX;
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
@@ -45,13 +47,13 @@ use ipc_channel::ipc;
|
||||
use ipc_channel::router::ROUTER;
|
||||
use microtask::{Microtask, MicrotaskRunnable};
|
||||
use mime::{Mime, TopLevel};
|
||||
use net_traits::{FetchResponseListener, FetchMetadata, NetworkError, FetchResponseMsg};
|
||||
use net_traits::{FetchResponseListener, FetchMetadata, NetworkError, FetchResponseMsg, ResourceFetchTiming};
|
||||
use net_traits::image::base::{Image, ImageMetadata};
|
||||
use net_traits::image_cache::{CanRequestImages, ImageCache, ImageOrMetadataAvailable};
|
||||
use net_traits::image_cache::{ImageResponder, ImageResponse, ImageState, PendingImageId};
|
||||
use net_traits::image_cache::UsePlaceholder;
|
||||
use net_traits::request::RequestInit;
|
||||
use network_listener::{NetworkListener, PreInvoke};
|
||||
use network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||
use num_traits::ToPrimitive;
|
||||
use script_thread::ScriptThread;
|
||||
use servo_url::ServoUrl;
|
||||
@@ -160,6 +162,11 @@ struct ImageContext {
|
||||
status: Result<(), NetworkError>,
|
||||
/// The cache ID for this request.
|
||||
id: PendingImageId,
|
||||
/// The document associated with this request
|
||||
doc: Trusted<Document>,
|
||||
/// timing data for this resource
|
||||
resource_timing: ResourceFetchTiming,
|
||||
url: ServoUrl,
|
||||
}
|
||||
|
||||
impl FetchResponseListener for ImageContext {
|
||||
@@ -198,9 +205,32 @@ impl FetchResponseListener for ImageContext {
|
||||
}
|
||||
|
||||
fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
|
||||
// notify_pending_response doesn't use the resource timing
|
||||
self.image_cache.notify_pending_response(
|
||||
self.id,
|
||||
FetchResponseMsg::ProcessResponseEOF(response));
|
||||
FetchResponseMsg::ProcessResponseEOF(response.map(|_| ResourceFetchTiming::new())));
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,6 +309,9 @@ impl HTMLImageElement {
|
||||
image_cache: window.image_cache(),
|
||||
status: Ok(()),
|
||||
id: id,
|
||||
doc: Trusted::new(&document),
|
||||
resource_timing: ResourceFetchTiming::new(),
|
||||
url: img_url.clone(),
|
||||
}));
|
||||
|
||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||
|
||||
@@ -24,10 +24,12 @@ use dom::blob::Blob;
|
||||
use dom::document::Document;
|
||||
use dom::element::{Element, AttributeMutation};
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::htmlsourceelement::HTMLSourceElement;
|
||||
use dom::mediaerror::MediaError;
|
||||
use dom::node::{window_from_node, document_from_node, Node, UnbindContext};
|
||||
use dom::performanceresourcetiming::InitiatorType;
|
||||
use dom::promise::Promise;
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use dom_struct::dom_struct;
|
||||
@@ -36,9 +38,9 @@ use ipc_channel::ipc;
|
||||
use ipc_channel::router::ROUTER;
|
||||
use microtask::{Microtask, MicrotaskRunnable};
|
||||
use mime::{Mime, SubLevel, TopLevel};
|
||||
use net_traits::{FetchResponseListener, FetchMetadata, Metadata, NetworkError};
|
||||
use net_traits::{FetchResponseListener, FetchMetadata, Metadata, NetworkError, ResourceFetchTiming};
|
||||
use net_traits::request::{CredentialsMode, Destination, RequestInit};
|
||||
use network_listener::{NetworkListener, PreInvoke};
|
||||
use network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||
use script_thread::ScriptThread;
|
||||
use servo_url::ServoUrl;
|
||||
use std::cell::Cell;
|
||||
@@ -591,7 +593,7 @@ impl HTMLMediaElement {
|
||||
HTMLMediaElementTypeId::HTMLVideoElement => Destination::Video,
|
||||
};
|
||||
let request = RequestInit {
|
||||
url,
|
||||
url: url.clone(),
|
||||
destination,
|
||||
credentials_mode: CredentialsMode::Include,
|
||||
use_url_credentials: true,
|
||||
@@ -602,7 +604,7 @@ impl HTMLMediaElement {
|
||||
.. RequestInit::default()
|
||||
};
|
||||
|
||||
let context = Arc::new(Mutex::new(HTMLMediaElementContext::new(self)));
|
||||
let context = Arc::new(Mutex::new(HTMLMediaElementContext::new(self, url)));
|
||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||
let window = window_from_node(self);
|
||||
let listener = NetworkListener {
|
||||
@@ -988,6 +990,10 @@ struct HTMLMediaElementContext {
|
||||
have_metadata: bool,
|
||||
/// 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
|
||||
@@ -1090,6 +1096,30 @@ 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 {
|
||||
@@ -1100,7 +1130,7 @@ impl PreInvoke for HTMLMediaElementContext {
|
||||
}
|
||||
|
||||
impl HTMLMediaElementContext {
|
||||
fn new(elem: &HTMLMediaElement) -> HTMLMediaElementContext {
|
||||
fn new(elem: &HTMLMediaElement, url: ServoUrl) -> HTMLMediaElementContext {
|
||||
HTMLMediaElementContext {
|
||||
elem: Trusted::new(elem),
|
||||
data: vec![],
|
||||
@@ -1109,6 +1139,8 @@ impl HTMLMediaElementContext {
|
||||
next_progress_event: time::get_time() + Duration::milliseconds(350),
|
||||
have_metadata: false,
|
||||
ignore_response: false,
|
||||
resource_timing: ResourceFetchTiming::new(),
|
||||
url: url,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ use dom::globalscope::GlobalScope;
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::node::{ChildrenMutation, CloneChildrenFlag, Node};
|
||||
use dom::node::{document_from_node, window_from_node};
|
||||
use dom::performanceresourcetiming::InitiatorType;
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use dom_struct::dom_struct;
|
||||
use encoding_rs::Encoding;
|
||||
@@ -28,9 +29,9 @@ use html5ever::{LocalName, Prefix};
|
||||
use ipc_channel::ipc;
|
||||
use ipc_channel::router::ROUTER;
|
||||
use js::jsval::UndefinedValue;
|
||||
use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
|
||||
use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError, ResourceFetchTiming};
|
||||
use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestInit, RequestMode};
|
||||
use network_listener::{NetworkListener, PreInvoke};
|
||||
use network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||
use servo_atoms::Atom;
|
||||
use servo_config::opts;
|
||||
use servo_url::ServoUrl;
|
||||
@@ -154,7 +155,10 @@ struct ScriptContext {
|
||||
/// The initial URL requested.
|
||||
url: ServoUrl,
|
||||
/// Indicates whether the request failed, and why
|
||||
status: Result<(), NetworkError>
|
||||
status: Result<(), NetworkError>,
|
||||
|
||||
/// Timing object for this resource
|
||||
resource_timing: ResourceFetchTiming,
|
||||
}
|
||||
|
||||
impl FetchResponseListener for ScriptContext {
|
||||
@@ -221,6 +225,30 @@ 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 {}
|
||||
@@ -267,7 +295,8 @@ fn fetch_a_classic_script(script: &HTMLScriptElement,
|
||||
data: vec!(),
|
||||
metadata: None,
|
||||
url: url.clone(),
|
||||
status: Ok(())
|
||||
status: Ok(()),
|
||||
resource_timing: ResourceFetchTiming::new(),
|
||||
}));
|
||||
|
||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||
|
||||
@@ -400,10 +400,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;
|
||||
|
||||
@@ -9,15 +9,16 @@ use dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceEntryList a
|
||||
use dom::bindings::error::{Error, Fallible};
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::num::Finite;
|
||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||
use dom::bindings::root::{Dom, DomRoot};
|
||||
use dom::bindings::reflector::{DomObject, reflect_dom_object};
|
||||
use dom::bindings::root::DomRoot;
|
||||
use dom::bindings::str::DOMString;
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::performanceentry::PerformanceEntry;
|
||||
use dom::performancemark::PerformanceMark;
|
||||
use dom::performancemeasure::PerformanceMeasure;
|
||||
use dom::performancenavigationtiming::PerformanceNavigationTiming;
|
||||
use dom::performanceobserver::PerformanceObserver as DOMPerformanceObserver;
|
||||
use dom::performancetiming::PerformanceTiming;
|
||||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use metrics::ToMs;
|
||||
@@ -110,8 +111,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>,
|
||||
@@ -119,18 +119,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),
|
||||
@@ -139,10 +130,9 @@ impl Performance {
|
||||
}
|
||||
|
||||
pub fn new(global: &GlobalScope,
|
||||
navigation_start: u64,
|
||||
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
|
||||
)
|
||||
@@ -249,21 +239,19 @@ 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
|
||||
@@ -271,6 +259,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.borrow().get_entries_by_name_and_type(None, None)
|
||||
|
||||
@@ -55,6 +55,10 @@ impl PerformanceEntry {
|
||||
pub fn start_time(&self) -> f64 {
|
||||
self.start_time
|
||||
}
|
||||
|
||||
pub fn duration(&self) -> f64 {
|
||||
self.duration
|
||||
}
|
||||
}
|
||||
|
||||
impl PerformanceEntryMethods for PerformanceEntry {
|
||||
|
||||
120
components/script/dom/performancenavigationtiming.rs
Normal file
120
components/script/dom/performancenavigationtiming.rs
Normal file
@@ -0,0 +1,120 @@
|
||||
/* 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 dom::bindings::codegen::Bindings::PerformanceBinding::DOMHighResTimeStamp;
|
||||
use dom::bindings::codegen::Bindings::PerformanceNavigationTimingBinding::{self, NavigationType};
|
||||
use dom::bindings::codegen::Bindings::PerformanceNavigationTimingBinding::PerformanceNavigationTimingMethods;
|
||||
use dom::bindings::num::Finite;
|
||||
use dom::bindings::reflector::reflect_dom_object;
|
||||
use dom::bindings::root::{Dom, DomRoot};
|
||||
use dom::document::Document;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::performanceresourcetiming::{InitiatorType, PerformanceResourceTiming};
|
||||
use dom_struct::dom_struct;
|
||||
|
||||
#[dom_struct]
|
||||
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn set_type(&mut self, nav_type: NavigationType) {
|
||||
self.nav_type = nav_type
|
||||
}
|
||||
|
||||
pub fn new(global: &GlobalScope,
|
||||
nav_start: u64,
|
||||
nav_start_precise: u64,
|
||||
document: &Document)
|
||||
-> DomRoot<PerformanceNavigationTiming> {
|
||||
reflect_dom_object(
|
||||
Box::new(PerformanceNavigationTiming::new_inherited(
|
||||
nav_start, nav_start_precise, document)),
|
||||
global, PerformanceNavigationTimingBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/
|
||||
impl PerformanceNavigationTimingMethods for PerformanceNavigationTiming {
|
||||
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-unloadeventstart
|
||||
fn UnloadEventStart(&self) -> DOMHighResTimeStamp {
|
||||
Finite::wrap(self.document.get_unload_event_start() as f64)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-unloadeventend
|
||||
fn UnloadEventEnd(&self) -> DOMHighResTimeStamp {
|
||||
Finite::wrap(self.document.get_unload_event_end() as f64)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-dominteractive
|
||||
fn DomInteractive(&self) -> DOMHighResTimeStamp {
|
||||
Finite::wrap(self.document.get_dom_interactive() as f64)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-domcontentloadedeventstart
|
||||
fn DomContentLoadedEventStart(&self) -> DOMHighResTimeStamp {
|
||||
Finite::wrap(self.document.get_dom_content_loaded_event_start() as f64)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-domcontentloadedeventstart
|
||||
fn DomContentLoadedEventEnd(&self) -> DOMHighResTimeStamp {
|
||||
Finite::wrap(self.document.get_dom_content_loaded_event_end() as f64)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-domcomplete
|
||||
fn DomComplete(&self) -> DOMHighResTimeStamp {
|
||||
Finite::wrap(self.document.get_dom_complete() as f64)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-loadeventstart
|
||||
fn LoadEventStart(&self) -> DOMHighResTimeStamp {
|
||||
Finite::wrap(self.document.get_load_event_start() as f64)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-loadeventend
|
||||
fn LoadEventEnd(&self) -> DOMHighResTimeStamp {
|
||||
Finite::wrap(self.document.get_load_event_end() as f64)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-type
|
||||
fn Type(&self) -> NavigationType {
|
||||
self.nav_type.clone()
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming-redirectcount
|
||||
fn RedirectCount(&self) -> u16 {
|
||||
self.document.get_redirect_count()
|
||||
}
|
||||
|
||||
// check-tidy: no specs after this line
|
||||
// Servo-only timing for when top-level content (not iframes) is complete
|
||||
fn TopLevelDomComplete(&self) -> DOMHighResTimeStamp {
|
||||
Finite::wrap(self.document.get_top_level_dom_complete() as f64)
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ use std::rc::Rc;
|
||||
const VALID_ENTRY_TYPES: &'static [&'static str] = &[
|
||||
"mark", // User Timing API
|
||||
"measure", // User Timing API
|
||||
// "resource", XXX Resource Timing API
|
||||
"resource", // Resource Timing API
|
||||
// "server", XXX Server Timing API
|
||||
"paint", // Paint Timing API
|
||||
];
|
||||
|
||||
238
components/script/dom/performanceresourcetiming.rs
Normal file
238
components/script/dom/performanceresourcetiming.rs
Normal file
@@ -0,0 +1,238 @@
|
||||
/* 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 dom::bindings::codegen::Bindings::PerformanceBinding::DOMHighResTimeStamp;
|
||||
use dom::bindings::codegen::Bindings::PerformanceResourceTimingBinding::{self, PerformanceResourceTimingMethods};
|
||||
use dom::bindings::num::Finite;
|
||||
use dom::bindings::reflector::reflect_dom_object;
|
||||
use dom::bindings::root::DomRoot;
|
||||
use dom::bindings::str::DOMString;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use 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 remove this allow statement when CSS and Beacon are used
|
||||
#[allow(dead_code)]
|
||||
pub enum InitiatorType {
|
||||
LocalName(String),
|
||||
CSS,
|
||||
Navigation,
|
||||
XMLHttpRequest,
|
||||
Fetch,
|
||||
Beacon,
|
||||
Other,
|
||||
}
|
||||
|
||||
#[dom_struct]
|
||||
pub struct PerformanceResourceTiming {
|
||||
entry: PerformanceEntry,
|
||||
#[ignore_malloc_size_of = ""]
|
||||
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::CSS => DOMString::from("css"),
|
||||
InitiatorType::Navigation => DOMString::from("navigation"),
|
||||
InitiatorType::XMLHttpRequest => DOMString::from("xmlhttprequest"),
|
||||
InitiatorType::Fetch => DOMString::from("fetch"),
|
||||
InitiatorType::Beacon => DOMString::from("beacon"),
|
||||
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-workerstart
|
||||
fn WorkerStart(&self) -> DOMHighResTimeStamp {
|
||||
Finite::wrap(self.worker_start)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-redirectstart
|
||||
fn RedirectStart(&self) -> DOMHighResTimeStamp {
|
||||
Finite::wrap(self.redirect_start)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-redirectend
|
||||
fn RedirectEnd(&self) -> DOMHighResTimeStamp {
|
||||
Finite::wrap(self.redirect_end)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-fetchstart
|
||||
fn FetchStart(&self) -> DOMHighResTimeStamp {
|
||||
// TODO
|
||||
Finite::wrap(self.fetch_start)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-domainlookupstart
|
||||
fn DomainLookupStart(&self) -> DOMHighResTimeStamp {
|
||||
// TODO
|
||||
Finite::wrap(self.domain_lookup_start)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-domainlookupend
|
||||
fn DomainLookupEnd(&self) -> DOMHighResTimeStamp {
|
||||
// TODO
|
||||
Finite::wrap(self.domain_lookup_end)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-connectstart
|
||||
fn ConnectStart(&self) -> DOMHighResTimeStamp {
|
||||
// TODO
|
||||
Finite::wrap(self.connect_start)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-connectend
|
||||
fn ConnectEnd(&self) -> DOMHighResTimeStamp {
|
||||
// TODO
|
||||
Finite::wrap(self.connect_end)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-secureconnectstart
|
||||
fn SecureConnectionStart(&self) -> DOMHighResTimeStamp {
|
||||
// TODO
|
||||
Finite::wrap(self.secure_connection_start)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-responseend
|
||||
fn ResponseEnd(&self) -> DOMHighResTimeStamp {
|
||||
// TODO
|
||||
Finite::wrap(self.response_end)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,102 +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 http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::bindings::codegen::Bindings::PerformanceTimingBinding;
|
||||
use dom::bindings::codegen::Bindings::PerformanceTimingBinding::PerformanceTimingMethods;
|
||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||
use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||
use dom::bindings::root::{Dom, DomRoot};
|
||||
use dom::document::Document;
|
||||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct PerformanceTiming {
|
||||
reflector_: Reflector,
|
||||
navigation_start: u64,
|
||||
navigation_start_precise: u64,
|
||||
document: Dom<Document>,
|
||||
}
|
||||
|
||||
impl PerformanceTiming {
|
||||
fn new_inherited(nav_start: u64,
|
||||
nav_start_precise: u64,
|
||||
document: &Document)
|
||||
-> PerformanceTiming {
|
||||
PerformanceTiming {
|
||||
reflector_: Reflector::new(),
|
||||
navigation_start: nav_start,
|
||||
navigation_start_precise: nav_start_precise,
|
||||
document: Dom::from_ref(document),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unrooted_must_root)]
|
||||
pub fn new(window: &Window,
|
||||
navigation_start: u64,
|
||||
navigation_start_precise: u64)
|
||||
-> DomRoot<PerformanceTiming> {
|
||||
let timing = PerformanceTiming::new_inherited(navigation_start,
|
||||
navigation_start_precise,
|
||||
&window.Document());
|
||||
reflect_dom_object(Box::new(timing),
|
||||
window,
|
||||
PerformanceTimingBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
impl PerformanceTimingMethods for PerformanceTiming {
|
||||
// https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-navigationStart
|
||||
fn NavigationStart(&self) -> u64 {
|
||||
self.navigation_start
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-domLoading
|
||||
fn DomLoading(&self) -> u64 {
|
||||
self.document.get_dom_loading()
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-domInteractive
|
||||
fn DomInteractive(&self) -> u64 {
|
||||
self.document.get_dom_interactive()
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-domContentLoadedEventStart
|
||||
fn DomContentLoadedEventStart(&self) -> u64 {
|
||||
self.document.get_dom_content_loaded_event_start()
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-domContentLoadedEventEnd
|
||||
fn DomContentLoadedEventEnd(&self) -> u64 {
|
||||
self.document.get_dom_content_loaded_event_end()
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-domComplete
|
||||
fn DomComplete(&self) -> u64 {
|
||||
self.document.get_dom_complete()
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-loadEventStart
|
||||
fn LoadEventStart(&self) -> u64 {
|
||||
self.document.get_load_event_start()
|
||||
}
|
||||
|
||||
// https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-loadEventEnd
|
||||
fn LoadEventEnd(&self) -> u64 {
|
||||
self.document.get_load_event_end()
|
||||
}
|
||||
|
||||
// check-tidy: no specs after this line
|
||||
// Servo-only timing for when top-level content (not iframes) is complete
|
||||
fn TopLevelDomComplete(&self) -> u64 {
|
||||
self.document.get_top_level_dom_complete()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl PerformanceTiming {
|
||||
pub fn navigation_start_precise(&self) -> u64 {
|
||||
self.navigation_start_precise
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||
use dom::bindings::codegen::Bindings::ServoParserBinding;
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||
use dom::bindings::root::{Dom, DomRoot, MutNullableDom, RootedReference};
|
||||
use dom::bindings::settings_stack::is_execution_stack_empty;
|
||||
use dom::bindings::str::DOMString;
|
||||
@@ -26,6 +26,8 @@ use dom::htmlimageelement::HTMLImageElement;
|
||||
use dom::htmlscriptelement::{HTMLScriptElement, ScriptResult};
|
||||
use dom::htmltemplateelement::HTMLTemplateElement;
|
||||
use dom::node::Node;
|
||||
use dom::performanceentry::PerformanceEntry;
|
||||
use dom::performancenavigationtiming::PerformanceNavigationTiming;
|
||||
use dom::processinginstruction::ProcessingInstruction;
|
||||
use dom::text::Text;
|
||||
use dom::virtualmethods::vtable_for;
|
||||
@@ -39,7 +41,7 @@ use hyper::header::ContentType;
|
||||
use hyper::mime::{Mime, SubLevel, TopLevel};
|
||||
use hyper_serde::Serde;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
|
||||
use net_traits::{FetchMetadata, FetchResponseListener, Metadata, NetworkError, ResourceFetchTiming};
|
||||
use network_listener::PreInvoke;
|
||||
use profile_traits::time::{TimerMetadata, TimerMetadataFrameType};
|
||||
use profile_traits::time::{TimerMetadataReflowType, ProfilerCategory, profile};
|
||||
@@ -599,6 +601,8 @@ pub struct ParserContext {
|
||||
id: PipelineId,
|
||||
/// The URL for this document.
|
||||
url: ServoUrl,
|
||||
/// timing data for this resource
|
||||
resource_timing: ResourceFetchTiming,
|
||||
}
|
||||
|
||||
impl ParserContext {
|
||||
@@ -608,6 +612,7 @@ impl ParserContext {
|
||||
is_synthesized_document: false,
|
||||
id: id,
|
||||
url: url,
|
||||
resource_timing: ResourceFetchTiming::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -740,11 +745,37 @@ impl FetchResponseListener for ParserContext {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
let performance_entry = PerformanceNavigationTiming::new(&document.global(), 0, 0, &document);
|
||||
document.global().performance().queue_entry(performance_entry.upcast::<PerformanceEntry>(), true);
|
||||
}
|
||||
}
|
||||
|
||||
impl PreInvoke for ParserContext {}
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* The origin of this IDL file is
|
||||
* https://w3c.github.io/navigation-timing/#dom-performancenavigationtiming
|
||||
*/
|
||||
|
||||
|
||||
enum NavigationType {
|
||||
"navigate",
|
||||
"reload",
|
||||
"back_forward",
|
||||
"prerender"
|
||||
};
|
||||
|
||||
[Exposed=Window]
|
||||
interface PerformanceNavigationTiming : PerformanceResourceTiming {
|
||||
readonly attribute DOMHighResTimeStamp unloadEventStart;
|
||||
readonly attribute DOMHighResTimeStamp unloadEventEnd;
|
||||
readonly attribute DOMHighResTimeStamp domInteractive;
|
||||
readonly attribute DOMHighResTimeStamp domContentLoadedEventStart;
|
||||
readonly attribute DOMHighResTimeStamp domContentLoadedEventEnd;
|
||||
readonly attribute DOMHighResTimeStamp domComplete;
|
||||
readonly attribute DOMHighResTimeStamp loadEventStart;
|
||||
readonly attribute DOMHighResTimeStamp loadEventEnd;
|
||||
readonly attribute NavigationType type;
|
||||
readonly attribute unsigned short redirectCount;
|
||||
// [Default] object toJSON();
|
||||
/* Servo-only attribute for measuring when the top-level document (not iframes) is complete. */
|
||||
[Pref="dom.testperf.enabled"]
|
||||
readonly attribute DOMHighResTimeStamp topLevelDomComplete;
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
/* 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();
|
||||
};
|
||||
@@ -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 http://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;
|
||||
};
|
||||
@@ -757,8 +757,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())
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -325,7 +325,6 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ use dom::globalscope::GlobalScope;
|
||||
use dom::headers::is_forbidden_header_name;
|
||||
use dom::htmlformelement::{encode_multipart_form_data, generate_boundary};
|
||||
use dom::node::Node;
|
||||
use dom::performanceresourcetiming::InitiatorType;
|
||||
use dom::progressevent::ProgressEvent;
|
||||
use dom::servoparser::ServoParser;
|
||||
use dom::urlsearchparams::URLSearchParams;
|
||||
@@ -54,11 +55,11 @@ use js::jsval::{JSVal, NullValue, UndefinedValue};
|
||||
use js::rust::wrappers::JS_ParseJSON;
|
||||
use js::typedarray::{ArrayBuffer, CreateWith};
|
||||
use net_traits::{FetchChannels, FetchMetadata, FilteredMetadata};
|
||||
use net_traits::{FetchResponseListener, NetworkError, ReferrerPolicy};
|
||||
use net_traits::{FetchResponseListener, NetworkError, ReferrerPolicy, ResourceFetchTiming};
|
||||
use net_traits::CoreResourceMsg::Fetch;
|
||||
use net_traits::request::{CredentialsMode, Destination, RequestInit, RequestMode};
|
||||
use net_traits::trim_http_whitespace;
|
||||
use network_listener::{NetworkListener, PreInvoke};
|
||||
use network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||
use script_traits::DocumentActivity;
|
||||
use servo_atoms::Atom;
|
||||
use servo_url::ServoUrl;
|
||||
@@ -95,6 +96,7 @@ struct XHRContext {
|
||||
gen_id: GenerationId,
|
||||
buf: DomRefCell<Vec<u8>>,
|
||||
sync_status: DomRefCell<Option<ErrorResult>>,
|
||||
resource_timing: ResourceFetchTiming,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -256,6 +258,28 @@ impl XMLHttpRequest {
|
||||
let rv = self.xhr.root().process_response_complete(self.gen_id, response);
|
||||
*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 {
|
||||
@@ -1318,6 +1342,7 @@ impl XMLHttpRequest {
|
||||
gen_id: self.generation_id.get(),
|
||||
buf: DomRefCell::new(vec!()),
|
||||
sync_status: DomRefCell::new(None),
|
||||
resource_timing: ResourceFetchTiming::new(),
|
||||
}));
|
||||
|
||||
let (task_source, script_port) = if self.sync.get() {
|
||||
|
||||
@@ -14,6 +14,7 @@ use dom::bindings::root::DomRoot;
|
||||
use dom::bindings::trace::RootedTraceableBox;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::headers::Guard;
|
||||
use dom::performanceresourcetiming::InitiatorType;
|
||||
use dom::promise::Promise;
|
||||
use dom::request::Request;
|
||||
use dom::response::Response;
|
||||
@@ -21,12 +22,12 @@ use dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
|
||||
use ipc_channel::ipc;
|
||||
use ipc_channel::router::ROUTER;
|
||||
use js::jsapi::JSAutoCompartment;
|
||||
use net_traits::{FetchChannels, FetchResponseListener, NetworkError};
|
||||
use net_traits::{FetchChannels, FetchResponseListener, NetworkError, ResourceFetchTiming};
|
||||
use net_traits::{FilteredMetadata, FetchMetadata, Metadata};
|
||||
use net_traits::CoreResourceMsg::Fetch as NetTraitsFetch;
|
||||
use net_traits::request::{Request as NetTraitsRequest, ServiceWorkersMode};
|
||||
use net_traits::request::RequestInit as NetTraitsRequestInit;
|
||||
use network_listener::{NetworkListener, PreInvoke};
|
||||
use network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||
use servo_url::ServoUrl;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
@@ -37,6 +38,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
|
||||
@@ -151,6 +153,7 @@ pub fn Fetch(global: &GlobalScope, input: RequestInfo, init: RootedTraceableBox<
|
||||
fetch_promise: Some(TrustedPromise::new(promise.clone())),
|
||||
response_object: Trusted::new(&*response),
|
||||
body: vec![],
|
||||
resource_timing: ResourceFetchTiming::new(),
|
||||
}));
|
||||
let listener = NetworkListener {
|
||||
context: fetch_context,
|
||||
@@ -236,6 +239,28 @@ 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) {
|
||||
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) {
|
||||
|
||||
@@ -7,14 +7,19 @@
|
||||
//! no guarantee that the responsible nodes will still exist in the future if the
|
||||
//! layout thread holds on to them during asynchronous operations.
|
||||
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::bindings::reflector::DomObject;
|
||||
use dom::bindings::root::DomRoot;
|
||||
use dom::document::Document;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::node::{Node, document_from_node};
|
||||
use dom::performanceresourcetiming::InitiatorType;
|
||||
use ipc_channel::ipc;
|
||||
use ipc_channel::router::ROUTER;
|
||||
use net_traits::{FetchResponseMsg, FetchResponseListener, FetchMetadata, NetworkError};
|
||||
use net_traits::{FetchResponseMsg, FetchResponseListener, FetchMetadata, NetworkError, ResourceFetchTiming};
|
||||
use net_traits::image_cache::{ImageCache, PendingImageId};
|
||||
use net_traits::request::{Destination, RequestInit as FetchRequestInit};
|
||||
use network_listener::{NetworkListener, PreInvoke};
|
||||
use network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||
use servo_url::ServoUrl;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use task_source::TaskSourceName;
|
||||
@@ -22,6 +27,8 @@ use task_source::TaskSourceName;
|
||||
struct LayoutImageContext {
|
||||
id: PendingImageId,
|
||||
cache: Arc<ImageCache>,
|
||||
resource_timing: ResourceFetchTiming,
|
||||
doc: Trusted<Document>,
|
||||
}
|
||||
|
||||
impl FetchResponseListener for LayoutImageContext {
|
||||
@@ -40,8 +47,32 @@ impl FetchResponseListener for LayoutImageContext {
|
||||
}
|
||||
|
||||
fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
|
||||
// TODO notify_pending_response doesn't use the ResourceFetchTiming
|
||||
self.cache.notify_pending_response(self.id,
|
||||
FetchResponseMsg::ProcessResponseEOF(response));
|
||||
FetchResponseMsg::ProcessResponseEOF(
|
||||
response.map(|_| ResourceFetchTiming::new())));
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,14 +82,16 @@ pub fn fetch_image_for_layout(url: ServoUrl,
|
||||
node: &Node,
|
||||
id: PendingImageId,
|
||||
cache: Arc<ImageCache>) {
|
||||
let document = document_from_node(node);
|
||||
let window = document.window();
|
||||
|
||||
let context = Arc::new(Mutex::new(LayoutImageContext {
|
||||
id: id,
|
||||
cache: cache,
|
||||
resource_timing: ResourceFetchTiming::new(),
|
||||
doc: Trusted::new(&document),
|
||||
}));
|
||||
|
||||
let document = document_from_node(node);
|
||||
let window = document.window();
|
||||
|
||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||
let listener = NetworkListener {
|
||||
context: context,
|
||||
|
||||
@@ -2,7 +2,13 @@
|
||||
* 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 dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::root::DomRoot;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::performanceentry::PerformanceEntry;
|
||||
use dom::performanceresourcetiming::{InitiatorType, PerformanceResourceTiming};
|
||||
use net_traits::{Action, FetchResponseListener, FetchResponseMsg};
|
||||
use servo_url::ServoUrl;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use task::{TaskCanceller, TaskOnce};
|
||||
use task_source::TaskSource;
|
||||
@@ -16,6 +22,19 @@ 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) {
|
||||
let (initiator_type, url) = listener.resource_timing_information();
|
||||
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 {
|
||||
|
||||
@@ -1280,7 +1280,8 @@ impl ScriptThread {
|
||||
match fetch_data {
|
||||
FetchResponseMsg::ProcessResponse(metadata) => self.handle_fetch_metadata(id, metadata),
|
||||
FetchResponseMsg::ProcessResponseChunk(chunk) => self.handle_fetch_chunk(id, chunk),
|
||||
FetchResponseMsg::ProcessResponseEOF(eof) => self.handle_fetch_eof(id, eof),
|
||||
// TODO don't throw away resource timing
|
||||
FetchResponseMsg::ProcessResponseEOF(eof) => self.handle_fetch_eof(id, eof.map(|_| ())),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
},
|
||||
@@ -2534,9 +2535,12 @@ impl ScriptThread {
|
||||
|
||||
fn handle_fetch_metadata(&self, id: PipelineId, 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().find(|&&mut (pipeline_id, _)| pipeline_id == id);
|
||||
if let Some(&mut (_, ref mut ctxt)) = parser {
|
||||
|
||||
@@ -7,12 +7,15 @@ use document_loader::LoadType;
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::refcounted::Trusted;
|
||||
use dom::bindings::reflector::DomObject;
|
||||
use dom::bindings::root::DomRoot;
|
||||
use dom::document::Document;
|
||||
use dom::element::Element;
|
||||
use dom::eventtarget::EventTarget;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::htmllinkelement::{RequestGenerationId, HTMLLinkElement};
|
||||
use dom::node::{document_from_node, window_from_node};
|
||||
use dom::performanceresourcetiming::InitiatorType;
|
||||
use encoding_rs::UTF_8;
|
||||
use hyper::header::ContentType;
|
||||
use hyper::mime::{Mime, TopLevel, SubLevel};
|
||||
@@ -20,8 +23,9 @@ use hyper_serde::Serde;
|
||||
use ipc_channel::ipc;
|
||||
use ipc_channel::router::ROUTER;
|
||||
use net_traits::{FetchResponseListener, FetchMetadata, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy};
|
||||
use net_traits::ResourceFetchTiming;
|
||||
use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestInit, RequestMode};
|
||||
use network_listener::{NetworkListener, PreInvoke};
|
||||
use network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||
use parking_lot::RwLock;
|
||||
use servo_arc::Arc;
|
||||
use servo_url::ServoUrl;
|
||||
@@ -78,6 +82,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 {}
|
||||
@@ -102,7 +107,7 @@ impl FetchResponseListener for StylesheetContext {
|
||||
self.metadata = metadata.ok().map(|m| {
|
||||
match m {
|
||||
FetchMetadata::Unfiltered(m) => m,
|
||||
FetchMetadata::Filtered { unsafe_, .. } => unsafe_
|
||||
FetchMetadata::Filtered { unsafe_, .. } => unsafe_,
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -193,6 +198,30 @@ 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> {
|
||||
@@ -223,6 +252,7 @@ impl<'a> StylesheetLoader<'a> {
|
||||
document: Trusted::new(&*document),
|
||||
origin_clean: true,
|
||||
request_generation_id: gen,
|
||||
resource_timing: ResourceFetchTiming::new(),
|
||||
}));
|
||||
|
||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||
|
||||
@@ -34,5 +34,3 @@
|
||||
[windows-1254: iso_8859-9:1989 (XMLHttpRequest)]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[single-byte-decoder.html?TextDecoder]
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
[test_cross_frame_start.html]
|
||||
[Child created at least 1 second after parent]
|
||||
expected: FAIL
|
||||
|
||||
[Child and parent time bases are correct]
|
||||
expected: FAIL
|
||||
|
||||
@@ -6,6 +6,3 @@
|
||||
[Window and worker timeOrigins are close when created one after another.]
|
||||
expected: FAIL
|
||||
|
||||
[Window and worker timeOrigins differ when worker is created after a delay.]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
[window-worker-timeOrigin.window.html]
|
||||
type: testharness
|
||||
[timeOrigin and now() should be correctly ordered between window and worker]
|
||||
expected: FAIL
|
||||
|
||||
@@ -292,7 +292,3 @@
|
||||
[<meta>: "1\\furl=foo"]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
||||
[parsing.html?131-last]
|
||||
|
||||
[parsing.html?81-90]
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[clear_resource_timing_functionality.html]
|
||||
expected: ERROR
|
||||
[4 resource timing entries should be stored in this page.]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[resource-timing-tojson.html]
|
||||
[Untitled]
|
||||
expected: FAIL
|
||||
|
||||
31
tests/wpt/metadata/resource-timing/resource-timing.html.ini
Normal file
31
tests/wpt/metadata/resource-timing/resource-timing.html.ini
Normal file
@@ -0,0 +1,31 @@
|
||||
[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
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[resource_TAO_cross_origin_redirect_chain.html]
|
||||
expected: ERROR
|
||||
[There should be one entry.]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[resource_TAO_origin.htm]
|
||||
expected: ERROR
|
||||
[The iframe should have one resource timing entry.]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[resource_TAO_zero.htm]
|
||||
expected: ERROR
|
||||
[There should be one resource timing entry.]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[resource_cached.htm]
|
||||
[There should be two entries]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[resource_connection_reuse.html]
|
||||
[There should be 2 PerformanceEntries]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[resource_dedicated_worker.html]
|
||||
[There should be six entries: 4 scripts, 1 stylesheet, and the worker itself]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
[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
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
[resource_memory_cached.sub.html]
|
||||
expected: ERROR
|
||||
[There should be only one entry]
|
||||
expected: FAIL
|
||||
|
||||
[http://web-platform.test:8000/resource-timing/resources/blue.png?id=cached is expected to be in the Resource Timing buffer]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
[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
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[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
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
[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
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
[resource_subframe_self_navigation.html]
|
||||
[Subsequent <iframe> navigations don't appear in the resource-timing buffer.]
|
||||
expected: FAIL
|
||||
|
||||
[Subsequent <frame> navigations don't appear in the resource-timing buffer.]
|
||||
expected: FAIL
|
||||
|
||||
[Subsequent <embed> navigations don't appear in the resource-timing buffer.]
|
||||
expected: FAIL
|
||||
|
||||
[Subsequent <object> navigations don't appear in the resource-timing buffer.]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[resource_timing.worker.html]
|
||||
[Performance Resouce Entries in workers]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[resource_timing_TAO_cross_origin_redirect.html]
|
||||
[This test validates the values in resource timing for a timing allowed cross-origin redirect.]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[resource_timing_buffer_full_when_populate_entries.html]
|
||||
[This test validates the functionality of onresourcetimingbufferfull in resource timing.]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[resource_timing_buffer_full_when_shrink_buffer_size.html]
|
||||
[This test validates the functionality of onresourcetimingbufferfull in resource timing.]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[resource_timing_cross_origin_redirect.html]
|
||||
[This test validates the values in resource timing for a cross-origin redirect.]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[resource_timing_cross_origin_redirect_chain.html]
|
||||
expected: ERROR
|
||||
[There should be one entry.]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[resource_timing_same_origin_redirect.html]
|
||||
[This test validates the values of the redirectStart/End in resource timing for a same-origin resource redirect.]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[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
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[single-entry-per-resource.html]
|
||||
[One resource when reusing data]
|
||||
expected: FAIL
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
[test_resource_timing.html]
|
||||
expected: TIMEOUT
|
||||
[window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (iframe)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct name, initiatorType, startTime, and duration (iframe)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct order of timing attributes (iframe)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct network transfer attributes (iframe)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct protocol attribute (iframe)]
|
||||
expected: FAIL
|
||||
|
||||
[window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (img)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct name, initiatorType, startTime, and duration (img)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct order of timing attributes (img)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct network transfer attributes (img)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct protocol attribute (img)]
|
||||
expected: FAIL
|
||||
|
||||
[window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (link)]
|
||||
expected: TIMEOUT
|
||||
|
||||
[PerformanceEntry has correct name, initiatorType, startTime, and duration (link)]
|
||||
expected: NOTRUN
|
||||
|
||||
[PerformanceEntry has correct order of timing attributes (link)]
|
||||
expected: NOTRUN
|
||||
|
||||
[PerformanceEntry has correct network transfer attributes (link)]
|
||||
expected: NOTRUN
|
||||
|
||||
[PerformanceEntry has correct protocol attribute (link)]
|
||||
expected: NOTRUN
|
||||
|
||||
[window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (script)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct name, initiatorType, startTime, and duration (script)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct order of timing attributes (script)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct network transfer attributes (script)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct protocol attribute (script)]
|
||||
expected: FAIL
|
||||
|
||||
[window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (xmlhttprequest)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct name, initiatorType, startTime, and duration (xmlhttprequest)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct order of timing attributes (xmlhttprequest)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct network transfer attributes (xmlhttprequest)]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceEntry has correct protocol attribute (xmlhttprequest)]
|
||||
expected: FAIL
|
||||
|
||||
@@ -4,5 +4,3 @@
|
||||
[WebSockets: Send/Receive blob, blob size less than network array buffer]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
||||
[001.html]
|
||||
|
||||
@@ -3,5 +3,3 @@
|
||||
[WebSockets: Send/Receive blob, blob size greater than network array buffer]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
||||
[002.html]
|
||||
|
||||
@@ -3,5 +3,3 @@
|
||||
[WebSockets: Send/Receive ArrayBuffer, size greater than network array buffer]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
||||
[004.html]
|
||||
|
||||
@@ -4,5 +4,3 @@
|
||||
[WebSockets: Send/Receive ArrayBuffer, size less than network array buffer]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
||||
[005.html]
|
||||
|
||||
@@ -4,5 +4,3 @@
|
||||
[WebSockets: bufferedAmount for ArrayBuffer]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
||||
[bufferedAmount-arraybuffer.html]
|
||||
|
||||
@@ -4,5 +4,3 @@
|
||||
[WebSockets: bufferedAmount for blob]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
||||
[bufferedAmount-blob.html]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[import-in-moduleworker.html]
|
||||
expected: ERROR
|
||||
[Base URL in module dedicated workers: import]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[sharedworker-in-worker.html]
|
||||
expected: ERROR
|
||||
[Base URL in workers: new SharedWorker()]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
[005.html]
|
||||
type: testharness
|
||||
expected: ERROR
|
||||
[dedicated worker in shared worker in dedicated worker]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -5,7 +5,3 @@
|
||||
[sync-no-timeout]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[sync-no-timeout.any.worker.html]
|
||||
|
||||
[sync-no-timeout.any.html]
|
||||
|
||||
@@ -65286,7 +65286,7 @@
|
||||
"testharness"
|
||||
],
|
||||
"mozilla/interfaces.html": [
|
||||
"079065a1870bb9d3f790e9e8a3e17417c7195204",
|
||||
"90c34c76967cabd320b20a1333bbf2a01928d285",
|
||||
"testharness"
|
||||
],
|
||||
"mozilla/interfaces.js": [
|
||||
@@ -65294,7 +65294,7 @@
|
||||
"support"
|
||||
],
|
||||
"mozilla/interfaces.worker.js": [
|
||||
"c9dcc4f24540914b3be1ef18f13b721773eb76be",
|
||||
"a7670abf3243ec4f2e4322bdbb4e5b88d5b2c76e",
|
||||
"testharness"
|
||||
],
|
||||
"mozilla/invalid-this.html": [
|
||||
@@ -71110,11 +71110,11 @@
|
||||
"testharness"
|
||||
],
|
||||
"mozilla/window_performance.html": [
|
||||
"f03283e68b82d972ad21f674243070643ef89489",
|
||||
"d782b6a9bcb1db5c8a622fa6f6e6336f7fcd2856",
|
||||
"testharness"
|
||||
],
|
||||
"mozilla/window_performance_topLevelDomComplete.html": [
|
||||
"4b953e63ffa6bf4ed1bc9a2baaea457d46502b9d",
|
||||
"3c02cebc0147a6ab31ee4cefa9b86d917525ecdf",
|
||||
"testharness"
|
||||
],
|
||||
"mozilla/window_requestAnimationFrame.html": [
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[window_performance.html]
|
||||
[window_performance]
|
||||
expected: FAIL
|
||||
|
||||
@@ -165,10 +165,11 @@ test_interfaces([
|
||||
"PerformanceEntry",
|
||||
"PerformanceMark",
|
||||
"PerformanceMeasure",
|
||||
"PerformanceNavigationTiming",
|
||||
"PerformanceObserver",
|
||||
"PerformanceObserverEntryList",
|
||||
"PerformancePaintTiming",
|
||||
"PerformanceTiming",
|
||||
"PerformanceResourceTiming",
|
||||
"Plugin",
|
||||
"PluginArray",
|
||||
"PopStateEvent",
|
||||
|
||||
@@ -36,9 +36,11 @@ test_interfaces([
|
||||
"PerformanceEntry",
|
||||
"PerformanceMark",
|
||||
"PerformanceMeasure",
|
||||
"PerformanceNavigationTiming",
|
||||
"PerformanceObserver",
|
||||
"PerformanceObserverEntryList",
|
||||
"PerformancePaintTiming",
|
||||
"PerformanceResourceTiming",
|
||||
"ProgressEvent",
|
||||
"Request",
|
||||
"Response",
|
||||
|
||||
@@ -11,9 +11,16 @@ 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);
|
||||
// FIXME(avada) I'm not sure performance.timing is working, but also we need to deprecate it
|
||||
assert_equals(window.performance.timing.startTime, entries[0].startTime);
|
||||
|
||||
|
||||
var last = window.performance.now();
|
||||
assert_greater_than(last, 0);
|
||||
|
||||
@@ -7,11 +7,15 @@
|
||||
<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();
|
||||
});
|
||||
window.onload = t.step_func(function () {
|
||||
var entries = performance.getEntries();
|
||||
assert_equals(entries.length, 1, "There should only be one navigation timing instance");
|
||||
|
||||
// The measurements are sometimes a few ns apart
|
||||
assert_true(Math.abs(entries[0].domComplete - entries[0].topLevelDomComplete) < 20);
|
||||
t.done()
|
||||
}
|
||||
);
|
||||
}, "performance.topLevelDomComplete");
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user