script/
layout_image.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Infrastructure to initiate network requests for images needed by layout. The script thread needs
6//! to be responsible for them because there's no guarantee that the responsible nodes will still
7//! exist in the future if layout holds on to them during asynchronous operations.
8
9use std::sync::Arc;
10
11use net_traits::image_cache::{ImageCache, PendingImageId};
12use net_traits::request::{Destination, RequestBuilder as FetchRequestInit, RequestId};
13use net_traits::{FetchMetadata, FetchResponseMsg, NetworkError, ResourceFetchTiming};
14use servo_url::ServoUrl;
15
16use crate::dom::bindings::refcounted::Trusted;
17use crate::dom::bindings::reflector::DomGlobal;
18use crate::dom::bindings::root::DomRoot;
19use crate::dom::csp::{GlobalCspReporting, Violation};
20use crate::dom::document::Document;
21use crate::dom::globalscope::GlobalScope;
22use crate::dom::node::{Node, NodeTraits};
23use crate::dom::performance::performanceresourcetiming::InitiatorType;
24use crate::network_listener::{self, FetchResponseListener, ResourceTimingListener};
25use crate::script_runtime::CanGc;
26
27struct LayoutImageContext {
28    id: PendingImageId,
29    cache: Arc<dyn ImageCache>,
30    doc: Trusted<Document>,
31    url: ServoUrl,
32}
33
34impl FetchResponseListener for LayoutImageContext {
35    fn process_request_body(&mut self, _: RequestId) {}
36    fn process_request_eof(&mut self, _: RequestId) {}
37    fn process_response(
38        &mut self,
39        request_id: RequestId,
40        metadata: Result<FetchMetadata, NetworkError>,
41    ) {
42        self.cache.notify_pending_response(
43            self.id,
44            FetchResponseMsg::ProcessResponse(request_id, metadata),
45        );
46    }
47
48    fn process_response_chunk(&mut self, request_id: RequestId, payload: Vec<u8>) {
49        self.cache.notify_pending_response(
50            self.id,
51            FetchResponseMsg::ProcessResponseChunk(request_id, payload.into()),
52        );
53    }
54
55    fn process_response_eof(
56        self,
57        request_id: RequestId,
58        response: Result<ResourceFetchTiming, NetworkError>,
59    ) {
60        self.cache.notify_pending_response(
61            self.id,
62            FetchResponseMsg::ProcessResponseEOF(request_id, response.clone()),
63        );
64        if let Ok(response) = response {
65            network_listener::submit_timing(&self, &response, CanGc::note());
66        }
67    }
68
69    fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
70        let global = &self.resource_timing_global();
71        global.report_csp_violations(violations, None, None);
72    }
73}
74
75impl ResourceTimingListener for LayoutImageContext {
76    fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
77        (InitiatorType::Other, self.url.clone())
78    }
79
80    fn resource_timing_global(&self) -> DomRoot<GlobalScope> {
81        self.doc.root().global()
82    }
83}
84
85pub(crate) fn fetch_image_for_layout(
86    url: ServoUrl,
87    node: &Node,
88    id: PendingImageId,
89    cache: Arc<dyn ImageCache>,
90) {
91    let document = node.owner_document();
92    let context = LayoutImageContext {
93        id,
94        cache,
95        doc: Trusted::new(&document),
96        url: url.clone(),
97    };
98
99    let request = FetchRequestInit::new(
100        Some(document.webview_id()),
101        url,
102        document.global().get_referrer(),
103    )
104    .origin(document.origin().immutable().clone())
105    .destination(Destination::Image)
106    .pipeline_id(Some(document.global().pipeline_id()))
107    .insecure_requests_policy(document.insecure_requests_policy())
108    .has_trustworthy_ancestor_origin(document.has_trustworthy_ancestor_origin())
109    .policy_container(document.policy_container().to_owned());
110
111    // Layout image loads do not delay the document load event.
112    document.fetch_background(request, context);
113}