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::blob_url_store::UrlWithBlobClaim;
12use net_traits::image_cache::{ImageCache, PendingImageId};
13use net_traits::request::{Destination, RequestBuilder, RequestId};
14use net_traits::{FetchMetadata, FetchResponseMsg, NetworkError, ResourceFetchTiming};
15use servo_url::ServoUrl;
16
17use crate::dom::bindings::refcounted::Trusted;
18use crate::dom::bindings::reflector::DomGlobal;
19use crate::dom::bindings::root::DomRoot;
20use crate::dom::csp::{GlobalCspReporting, Violation};
21use crate::dom::document::Document;
22use crate::dom::globalscope::GlobalScope;
23use crate::dom::node::{Node, NodeTraits};
24use crate::dom::performance::performanceresourcetiming::InitiatorType;
25use crate::fetch::RequestWithGlobalScope;
26use crate::network_listener::{self, FetchResponseListener, ResourceTimingListener};
27
28struct LayoutImageContext {
29    id: PendingImageId,
30    cache: Arc<dyn ImageCache>,
31    doc: Trusted<Document>,
32    url: ServoUrl,
33}
34
35impl FetchResponseListener for LayoutImageContext {
36    fn process_request_body(&mut self, _: RequestId) {}
37    fn process_response(
38        &mut self,
39        _: &mut js::context::JSContext,
40        request_id: RequestId,
41        metadata: Result<FetchMetadata, NetworkError>,
42    ) {
43        self.cache.notify_pending_response(
44            self.id,
45            FetchResponseMsg::ProcessResponse(request_id, metadata),
46        );
47    }
48
49    fn process_response_chunk(
50        &mut self,
51        _: &mut js::context::JSContext,
52        request_id: RequestId,
53        payload: Vec<u8>,
54    ) {
55        self.cache.notify_pending_response(
56            self.id,
57            FetchResponseMsg::ProcessResponseChunk(request_id, payload.into()),
58        );
59    }
60
61    fn process_response_eof(
62        self,
63        cx: &mut js::context::JSContext,
64        request_id: RequestId,
65        response: Result<(), NetworkError>,
66        timing: ResourceFetchTiming,
67    ) {
68        self.cache.notify_pending_response(
69            self.id,
70            FetchResponseMsg::ProcessResponseEOF(request_id, response.clone(), timing.clone()),
71        );
72        network_listener::submit_timing(cx, &self, &response, &timing);
73    }
74
75    fn process_csp_violations(&mut self, _request_id: RequestId, violations: Vec<Violation>) {
76        let global = &self.resource_timing_global();
77        global.report_csp_violations(violations, None, None);
78    }
79}
80
81impl ResourceTimingListener for LayoutImageContext {
82    fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
83        (InitiatorType::Other, self.url.clone())
84    }
85
86    fn resource_timing_global(&self) -> DomRoot<GlobalScope> {
87        self.doc.root().global()
88    }
89}
90
91pub(crate) fn fetch_image_for_layout(
92    url: ServoUrl,
93    node: &Node,
94    id: PendingImageId,
95    cache: Arc<dyn ImageCache>,
96) {
97    let document = node.owner_document();
98    let context = LayoutImageContext {
99        id,
100        cache,
101        doc: Trusted::new(&document),
102        url: url.clone(),
103    };
104
105    let global = node.owner_global();
106    let request = RequestBuilder::new(
107        Some(document.webview_id()),
108        UrlWithBlobClaim::from_url_without_having_claimed_blob(url),
109        global.get_referrer(),
110    )
111    .destination(Destination::Image)
112    .with_global_scope(&global);
113
114    // Layout image loads do not delay the document load event.
115    document.fetch_background(request, context);
116}