mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Create resource timing entry for sync network fetch
This commit is contained in:
parent
ea71b35220
commit
e5217eed0e
7 changed files with 131 additions and 90 deletions
|
@ -597,38 +597,6 @@ pub enum CookieSource {
|
|||
NonHTTP,
|
||||
}
|
||||
|
||||
/// Convenience function for synchronously loading a whole resource.
|
||||
pub fn load_whole_resource(
|
||||
request: RequestBuilder,
|
||||
core_resource_thread: &CoreResourceThread,
|
||||
) -> Result<(Metadata, Vec<u8>), NetworkError> {
|
||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||
core_resource_thread
|
||||
.send(CoreResourceMsg::Fetch(
|
||||
request,
|
||||
FetchChannels::ResponseMsg(action_sender, None),
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let mut buf = vec![];
|
||||
let mut metadata = None;
|
||||
loop {
|
||||
match action_receiver.recv().unwrap() {
|
||||
FetchResponseMsg::ProcessRequestBody | FetchResponseMsg::ProcessRequestEOF => (),
|
||||
FetchResponseMsg::ProcessResponse(Ok(m)) => {
|
||||
metadata = Some(match m {
|
||||
FetchMetadata::Unfiltered(m) => m,
|
||||
FetchMetadata::Filtered { unsafe_, .. } => unsafe_,
|
||||
})
|
||||
},
|
||||
FetchResponseMsg::ProcessResponseChunk(data) => buf.extend_from_slice(&data),
|
||||
FetchResponseMsg::ProcessResponseEOF(Ok(_)) => return Ok((metadata.unwrap(), buf)),
|
||||
FetchResponseMsg::ProcessResponse(Err(e)) |
|
||||
FetchResponseMsg::ProcessResponseEOF(Err(e)) => return Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Network errors that have to be exported out of the loaders
|
||||
#[derive(Clone, Debug, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum NetworkError {
|
||||
|
|
|
@ -22,6 +22,7 @@ use crate::dom::globalscope::GlobalScope;
|
|||
use crate::dom::messageevent::MessageEvent;
|
||||
use crate::dom::worker::{TrustedWorkerAddress, Worker};
|
||||
use crate::dom::workerglobalscope::WorkerGlobalScope;
|
||||
use crate::fetch::load_whole_resource;
|
||||
use crate::script_runtime::ScriptThreadEventCategory::WorkerEvent;
|
||||
use crate::script_runtime::{new_child_runtime, CommonScriptMsg, Runtime, ScriptChan, ScriptPort};
|
||||
use crate::task_queue::{QueuedTask, QueuedTaskConversion, TaskQueue};
|
||||
|
@ -37,7 +38,7 @@ use js::jsval::UndefinedValue;
|
|||
use js::rust::HandleValue;
|
||||
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId};
|
||||
use net_traits::request::{CredentialsMode, Destination, Referrer, RequestBuilder};
|
||||
use net_traits::{load_whole_resource, IpcSend};
|
||||
use net_traits::IpcSend;
|
||||
use script_traits::{TimerEvent, TimerSource, WorkerGlobalScopeInit, WorkerScriptLoadOrigin};
|
||||
use servo_rand::random;
|
||||
use servo_url::ServoUrl;
|
||||
|
@ -316,25 +317,6 @@ impl DedicatedWorkerGlobalScope {
|
|||
.referrer_policy(referrer_policy)
|
||||
.origin(origin);
|
||||
|
||||
let (metadata, bytes) =
|
||||
match load_whole_resource(request, &init.resource_threads.sender()) {
|
||||
Err(_) => {
|
||||
println!("error loading script {}", serialized_worker_url);
|
||||
parent_sender
|
||||
.send(CommonScriptMsg::Task(
|
||||
WorkerEvent,
|
||||
Box::new(SimpleWorkerErrorHandler::new(worker)),
|
||||
pipeline_id,
|
||||
TaskSourceName::DOMManipulation,
|
||||
))
|
||||
.unwrap();
|
||||
return;
|
||||
},
|
||||
Ok((metadata, bytes)) => (metadata, bytes),
|
||||
};
|
||||
let url = metadata.final_url;
|
||||
let source = String::from_utf8_lossy(&bytes);
|
||||
|
||||
let runtime = unsafe { new_child_runtime(parent) };
|
||||
|
||||
let (devtools_mpsc_chan, devtools_mpsc_port) = unbounded();
|
||||
|
@ -356,7 +338,7 @@ impl DedicatedWorkerGlobalScope {
|
|||
|
||||
let global = DedicatedWorkerGlobalScope::new(
|
||||
init,
|
||||
url,
|
||||
worker_url,
|
||||
devtools_mpsc_port,
|
||||
runtime,
|
||||
parent_sender.clone(),
|
||||
|
@ -369,6 +351,29 @@ impl DedicatedWorkerGlobalScope {
|
|||
// FIXME(njn): workers currently don't have a unique ID suitable for using in reporter
|
||||
// registration (#6631), so we instead use a random number and cross our fingers.
|
||||
let scope = global.upcast::<WorkerGlobalScope>();
|
||||
let global_scope = global.upcast::<GlobalScope>();
|
||||
|
||||
let (metadata, bytes) = match load_whole_resource(
|
||||
request,
|
||||
&global_scope.resource_threads().sender(),
|
||||
&global_scope,
|
||||
) {
|
||||
Err(_) => {
|
||||
println!("error loading script {}", serialized_worker_url);
|
||||
parent_sender
|
||||
.send(CommonScriptMsg::Task(
|
||||
WorkerEvent,
|
||||
Box::new(SimpleWorkerErrorHandler::new(worker)),
|
||||
pipeline_id,
|
||||
TaskSourceName::DOMManipulation,
|
||||
))
|
||||
.unwrap();
|
||||
return;
|
||||
},
|
||||
Ok((metadata, bytes)) => (metadata, bytes),
|
||||
};
|
||||
scope.set_url(metadata.final_url);
|
||||
let source = String::from_utf8_lossy(&bytes);
|
||||
|
||||
unsafe {
|
||||
// Handle interrupt requests
|
||||
|
|
|
@ -19,6 +19,7 @@ use crate::dom::extendablemessageevent::ExtendableMessageEvent;
|
|||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::worker::TrustedWorkerAddress;
|
||||
use crate::dom::workerglobalscope::WorkerGlobalScope;
|
||||
use crate::fetch::load_whole_resource;
|
||||
use crate::script_runtime::{new_rt_and_cx, CommonScriptMsg, Runtime, ScriptChan};
|
||||
use crate::task_queue::{QueuedTask, QueuedTaskConversion, TaskQueue};
|
||||
use crate::task_source::TaskSourceName;
|
||||
|
@ -31,7 +32,7 @@ use js::jsapi::{JSAutoCompartment, JSContext, JS_AddInterruptCallback};
|
|||
use js::jsval::UndefinedValue;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::request::{CredentialsMode, Destination, Referrer, RequestBuilder};
|
||||
use net_traits::{load_whole_resource, CustomResponseMediator, IpcSend};
|
||||
use net_traits::{CustomResponseMediator, IpcSend};
|
||||
use script_traits::{
|
||||
ScopeThings, ServiceWorkerMsg, TimerEvent, WorkerGlobalScopeInit, WorkerScriptLoadOrigin,
|
||||
};
|
||||
|
@ -292,8 +293,11 @@ impl ServiceWorkerGlobalScope {
|
|||
.referrer_policy(referrer_policy)
|
||||
.origin(origin);
|
||||
|
||||
let (url, source) =
|
||||
match load_whole_resource(request, &init.resource_threads.sender()) {
|
||||
let (url, source) = match load_whole_resource(
|
||||
request,
|
||||
&init.resource_threads.sender(),
|
||||
&GlobalScope::current().expect("No current global object"),
|
||||
) {
|
||||
Err(_) => {
|
||||
println!("error loading script {}", serialized_worker_url);
|
||||
return;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
||||
use crate::dom::bindings::codegen::Bindings::RequestBinding::RequestInit;
|
||||
use crate::dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
|
||||
|
@ -42,10 +43,11 @@ use js::panic::maybe_resume_unwind;
|
|||
use js::rust::{HandleValue, ParentRuntime};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::request::{CredentialsMode, Destination, RequestBuilder as NetRequestInit};
|
||||
use net_traits::{load_whole_resource, IpcSend};
|
||||
use net_traits::IpcSend;
|
||||
use script_traits::WorkerGlobalScopeInit;
|
||||
use script_traits::{TimerEvent, TimerEventId};
|
||||
use servo_url::{MutableOrigin, ServoUrl};
|
||||
use std::cell::Ref;
|
||||
use std::default::Default;
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
@ -78,7 +80,7 @@ pub struct WorkerGlobalScope {
|
|||
globalscope: GlobalScope,
|
||||
|
||||
worker_id: WorkerId,
|
||||
worker_url: ServoUrl,
|
||||
worker_url: DomRefCell<ServoUrl>,
|
||||
#[ignore_malloc_size_of = "Arc"]
|
||||
closing: Option<Arc<AtomicBool>>,
|
||||
#[ignore_malloc_size_of = "Defined in js"]
|
||||
|
@ -123,7 +125,7 @@ impl WorkerGlobalScope {
|
|||
Default::default(),
|
||||
),
|
||||
worker_id: init.worker_id,
|
||||
worker_url,
|
||||
worker_url: DomRefCell::new(worker_url),
|
||||
closing,
|
||||
runtime,
|
||||
location: Default::default(),
|
||||
|
@ -159,8 +161,12 @@ impl WorkerGlobalScope {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_url(&self) -> &ServoUrl {
|
||||
&self.worker_url
|
||||
pub fn get_url(&self) -> Ref<ServoUrl> {
|
||||
self.worker_url.borrow()
|
||||
}
|
||||
|
||||
pub fn set_url(&self, url: ServoUrl) {
|
||||
*self.worker_url.borrow_mut() = url;
|
||||
}
|
||||
|
||||
pub fn get_worker_id(&self) -> WorkerId {
|
||||
|
@ -187,7 +193,7 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
|
|||
// https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-location
|
||||
fn Location(&self) -> DomRoot<WorkerLocation> {
|
||||
self.location
|
||||
.or_init(|| WorkerLocation::new(self, self.worker_url.clone()))
|
||||
.or_init(|| WorkerLocation::new(self, self.worker_url.borrow().clone()))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#handler-workerglobalscope-onerror
|
||||
|
@ -197,7 +203,7 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
|
|||
fn ImportScripts(&self, url_strings: Vec<DOMString>) -> ErrorResult {
|
||||
let mut urls = Vec::with_capacity(url_strings.len());
|
||||
for url in url_strings {
|
||||
let url = self.worker_url.join(&url);
|
||||
let url = self.worker_url.borrow().join(&url);
|
||||
match url {
|
||||
Ok(url) => urls.push(url),
|
||||
Err(_) => return Err(Error::Syntax),
|
||||
|
@ -215,12 +221,13 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope {
|
|||
.pipeline_id(Some(self.upcast::<GlobalScope>().pipeline_id()))
|
||||
.referrer_policy(None);
|
||||
|
||||
let (url, source) =
|
||||
match load_whole_resource(request, &global_scope.resource_threads().sender()) {
|
||||
let (url, source) = match fetch::load_whole_resource(
|
||||
request,
|
||||
&global_scope.resource_threads().sender(),
|
||||
&global_scope,
|
||||
) {
|
||||
Err(_) => return Err(Error::Network),
|
||||
Ok((metadata, bytes)) => {
|
||||
(metadata.final_url, String::from_utf8(bytes).unwrap())
|
||||
},
|
||||
Ok((metadata, bytes)) => (metadata.final_url, String::from_utf8(bytes).unwrap()),
|
||||
};
|
||||
|
||||
let result = self.runtime.evaluate_script(
|
||||
|
@ -381,7 +388,7 @@ impl WorkerGlobalScope {
|
|||
match self.runtime.evaluate_script(
|
||||
self.reflector().get_jsobject(),
|
||||
&source,
|
||||
self.worker_url.as_str(),
|
||||
self.worker_url.borrow().as_str(),
|
||||
1,
|
||||
rval.handle_mut(),
|
||||
) {
|
||||
|
|
|
@ -33,6 +33,7 @@ use crate::dom::workletglobalscope::WorkletGlobalScope;
|
|||
use crate::dom::workletglobalscope::WorkletGlobalScopeInit;
|
||||
use crate::dom::workletglobalscope::WorkletGlobalScopeType;
|
||||
use crate::dom::workletglobalscope::WorkletTask;
|
||||
use crate::fetch::load_whole_resource;
|
||||
use crate::script_runtime::new_rt_and_cx;
|
||||
use crate::script_runtime::CommonScriptMsg;
|
||||
use crate::script_runtime::Runtime;
|
||||
|
@ -47,7 +48,6 @@ use js::jsapi::JSTracer;
|
|||
use js::jsapi::JS_GetGCParameter;
|
||||
use js::jsapi::JS_GC;
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::load_whole_resource;
|
||||
use net_traits::request::Destination;
|
||||
use net_traits::request::RequestBuilder;
|
||||
use net_traits::request::RequestMode;
|
||||
|
@ -631,7 +631,11 @@ impl WorkletThread {
|
|||
.credentials_mode(credentials.into())
|
||||
.origin(origin);
|
||||
|
||||
let script = load_whole_resource(request, &resource_fetcher)
|
||||
let script = load_whole_resource(
|
||||
request,
|
||||
&resource_fetcher,
|
||||
&global_scope.upcast::<GlobalScope>(),
|
||||
)
|
||||
.ok()
|
||||
.and_then(|(_, bytes)| String::from_utf8(bytes).ok());
|
||||
|
||||
|
|
|
@ -20,7 +20,9 @@ use crate::dom::promise::Promise;
|
|||
use crate::dom::request::Request;
|
||||
use crate::dom::response::Response;
|
||||
use crate::dom::serviceworkerglobalscope::ServiceWorkerGlobalScope;
|
||||
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
|
||||
use crate::network_listener::{
|
||||
self, submit_timing_data, NetworkListener, PreInvoke, ResourceTimingListener,
|
||||
};
|
||||
use crate::task_source::TaskSourceName;
|
||||
use ipc_channel::ipc;
|
||||
use ipc_channel::router::ROUTER;
|
||||
|
@ -28,6 +30,7 @@ use js::jsapi::JSAutoCompartment;
|
|||
use net_traits::request::RequestBuilder;
|
||||
use net_traits::request::{Request as NetTraitsRequest, ServiceWorkersMode};
|
||||
use net_traits::CoreResourceMsg::Fetch as NetTraitsFetch;
|
||||
use net_traits::{CoreResourceMsg, CoreResourceThread, FetchResponseMsg};
|
||||
use net_traits::{FetchChannels, FetchResponseListener, NetworkError};
|
||||
use net_traits::{FetchMetadata, FilteredMetadata, Metadata};
|
||||
use net_traits::{ResourceFetchTiming, ResourceTimingType};
|
||||
|
@ -301,3 +304,43 @@ fn fill_headers_with_metadata(r: DomRoot<Response>, m: Metadata) {
|
|||
r.set_raw_status(m.status);
|
||||
r.set_final_url(m.final_url);
|
||||
}
|
||||
|
||||
/// Convenience function for synchronously loading a whole resource.
|
||||
pub fn load_whole_resource(
|
||||
request: RequestBuilder,
|
||||
core_resource_thread: &CoreResourceThread,
|
||||
global: &GlobalScope,
|
||||
) -> Result<(Metadata, Vec<u8>), NetworkError> {
|
||||
let (action_sender, action_receiver) = ipc::channel().unwrap();
|
||||
let url = request.url.clone();
|
||||
core_resource_thread
|
||||
.send(CoreResourceMsg::Fetch(
|
||||
request,
|
||||
FetchChannels::ResponseMsg(action_sender, None),
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let mut buf = vec![];
|
||||
let mut metadata = None;
|
||||
loop {
|
||||
match action_receiver.recv().unwrap() {
|
||||
FetchResponseMsg::ProcessRequestBody | FetchResponseMsg::ProcessRequestEOF => (),
|
||||
FetchResponseMsg::ProcessResponse(Ok(m)) => {
|
||||
metadata = Some(match m {
|
||||
FetchMetadata::Unfiltered(m) => m,
|
||||
FetchMetadata::Filtered { unsafe_, .. } => unsafe_,
|
||||
})
|
||||
},
|
||||
FetchResponseMsg::ProcessResponseChunk(data) => buf.extend_from_slice(&data),
|
||||
FetchResponseMsg::ProcessResponseEOF(Ok(_)) => {
|
||||
let metadata = metadata.unwrap();
|
||||
if let Some(timing) = &metadata.timing {
|
||||
submit_timing_data(global, url, InitiatorType::Other, &timing);
|
||||
}
|
||||
return Ok((metadata, buf));
|
||||
},
|
||||
FetchResponseMsg::ProcessResponse(Err(e)) |
|
||||
FetchResponseMsg::ProcessResponseEOF(Err(e)) => return Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,9 @@ use crate::dom::performanceresourcetiming::{InitiatorType, PerformanceResourceTi
|
|||
use crate::task::{TaskCanceller, TaskOnce};
|
||||
use crate::task_source::networking::NetworkingTaskSource;
|
||||
use crate::task_source::TaskSource;
|
||||
use net_traits::{Action, FetchResponseListener, FetchResponseMsg, ResourceTimingType};
|
||||
use net_traits::{
|
||||
Action, FetchResponseListener, FetchResponseMsg, ResourceFetchTiming, ResourceTimingType,
|
||||
};
|
||||
use servo_url::ServoUrl;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
|
@ -42,14 +44,22 @@ pub fn submit_timing<T: ResourceTimingListener + FetchResponseListener>(listener
|
|||
return;
|
||||
}
|
||||
|
||||
let global = listener.resource_timing_global();
|
||||
let performance_entry = PerformanceResourceTiming::new(
|
||||
&global,
|
||||
submit_timing_data(
|
||||
&listener.resource_timing_global(),
|
||||
url,
|
||||
initiator_type,
|
||||
None,
|
||||
&listener.resource_timing(),
|
||||
listener.resource_timing(),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn submit_timing_data(
|
||||
global: &GlobalScope,
|
||||
url: ServoUrl,
|
||||
initiator_type: InitiatorType,
|
||||
resource_timing: &ResourceFetchTiming,
|
||||
) {
|
||||
let performance_entry =
|
||||
PerformanceResourceTiming::new(global, url, initiator_type, None, resource_timing);
|
||||
global
|
||||
.performance()
|
||||
.queue_entry(performance_entry.upcast::<PerformanceEntry>(), false);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue