Repository: servo/servo
File: components/script/network_listener.rs (Rust)

Code before:
use crate::dom::bindings::root::DomRoot;
use crate::dom::globalscope::GlobalScope;
use crate::dom::performance::performanceentry::PerformanceEntry;
use crate::dom::performance::performanceresourcetiming::{
    InitiatorType, PerformanceResourceTiming,
};
use crate::script_runtime::CanGc;
use crate::task_source::SendableTaskSource;

pub(crate) trait ResourceTimingListener {
    fn resource_timing_information(&self) -> (InitiatorType, ServoUrl);
    fn resource_timing_global(&self) -> DomRoot<GlobalScope>;
}

pub(crate) fn submit_timing<T: ResourceTimingListener>(
    listener: &T,
    result: &Result<(), NetworkError>,
    resource_timing: &ResourceFetchTiming,
    can_gc: CanGc,
) {
    if let Err(
        NetworkError::ContentSecurityPolicy |
        NetworkError::MixedContent |
        NetworkError::SubresourceIntegrity |
        NetworkError::Nosniff |
        NetworkError::InvalidPort |
        NetworkError::CorsGeneral |
        NetworkError::CrossOriginResponse |
        NetworkError::CorsCredentials |
        NetworkError::CorsAllowMethods |
        NetworkError::CorsAllowHeaders |
        NetworkError::CorsMethod |
        NetworkError::CorsAuthorization |
        NetworkError::CorsHeaders,
    ) = &result
    {
        // timing check https://w3c.github.io/resource-timing/#dfn-timing-allow-check
        return;
    }

    // Resource timings should only be submitted for the initial preload request,
    // not for the request that consumes the preload: https://github.com/whatwg/html/issues/12047
    if resource_timing.preloaded {
        return;
    }
    // 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.
    if resource_timing.timing_type != ResourceTimingType::Resource &&
        resource_timing.timing_type != ResourceTimingType::Error

Review comment (bug):
Let's add a reference to the spec as listed in the original issue

```suggestion
    // https://www.w3.org/TR/resource-timing/#resources-included-in-the-performanceresourcetiming-interface
    // If a resource fetch is aborted because it failed a fetch precondition
    // (e.g. mixed content, CORS restriction, CSP policy, etc), then this resource
    // will not be included as a PerformanceResourceTiming object in
    // the Performance Timeline.
    if let Err(
```

Code after:
use crate::dom::bindings::root::DomRoot;
use crate::dom::globalscope::GlobalScope;
use crate::dom::performance::performanceentry::PerformanceEntry;
use crate::dom::performance::performanceresourcetiming::{
    InitiatorType, PerformanceResourceTiming,
};
use crate::script_runtime::CanGc;
use crate::task_source::SendableTaskSource;

pub(crate) trait ResourceTimingListener {
    fn resource_timing_information(&self) -> (InitiatorType, ServoUrl);
    fn resource_timing_global(&self) -> DomRoot<GlobalScope>;
}

pub(crate) fn submit_timing<T: ResourceTimingListener>(
    listener: &T,
    result: &Result<(), NetworkError>,
    resource_timing: &ResourceFetchTiming,
    can_gc: CanGc,
) {
    // https://www.w3.org/TR/resource-timing/#resources-included-in-the-performanceresourcetiming-interface
    // If a resource fetch is aborted because it failed a fetch precondition
    // (e.g. mixed content, CORS restriction, CSP policy, etc), then this resource
    // will not be included as a PerformanceResourceTiming object in
    // the Performance Timeline.
    if let Err(
        NetworkError::ContentSecurityPolicy |
        NetworkError::MixedContent |
        NetworkError::SubresourceIntegrity |
        NetworkError::Nosniff |
        NetworkError::InvalidPort |
        NetworkError::CorsGeneral |
        NetworkError::CrossOriginResponse |
        NetworkError::CorsCredentials |
        NetworkError::CorsAllowMethods |
        NetworkError::CorsAllowHeaders |
        NetworkError::CorsMethod |
        NetworkError::CorsAuthorization |
        NetworkError::CorsHeaders,
    ) = &result
    {
        return;
    }

    // Resource timings should only be submitted for the initial preload request,
    // not for the request that consumes the preload: https://github.com/whatwg/html/issues/12047
    if resource_timing.preloaded {
        return;
    }
    // TODO Resources for which the fetch was initiated, but was later aborted
    // (e.g. due to a network error) MAY be included as PerformanceResourceTiming