script/dom/window/
layout_image.rs1use std::sync::Arc;
10
11use bytes::Bytes;
12use net_traits::blob_url_store::UrlWithBlobClaim;
13use net_traits::image_cache::{ImageCache, PendingImageId};
14use net_traits::request::{Destination, InternalRequest, RequestBuilder, RequestId};
15use net_traits::{FetchMetadata, FetchResponseMsg, NetworkError, ResourceFetchTiming};
16use servo_url::ServoUrl;
17
18use crate::dom::bindings::refcounted::Trusted;
19use crate::dom::bindings::reflector::DomGlobal;
20use crate::dom::bindings::root::DomRoot;
21use crate::dom::csp::{GlobalCspReporting, Violation};
22use crate::dom::document::Document;
23use crate::dom::globalscope::GlobalScope;
24use crate::dom::node::{Node, NodeTraits};
25use crate::dom::performance::performanceresourcetiming::InitiatorType;
26use crate::event_loop::document_loader::LoadType;
27use crate::fetch::fetch::RequestWithGlobalScope;
28use crate::fetch::network_listener::{self, FetchResponseListener, ResourceTimingListener};
29
30struct LayoutImageContext {
31 id: PendingImageId,
32 cache: Arc<dyn ImageCache>,
33 doc: Trusted<Document>,
34 url: ServoUrl,
35}
36
37impl FetchResponseListener for LayoutImageContext {
38 fn process_request_body(&mut self, _: RequestId) {}
39 fn process_response(
40 &mut self,
41 _: &mut js::context::JSContext,
42 request_id: RequestId,
43 metadata: Result<FetchMetadata, NetworkError>,
44 ) {
45 self.cache.notify_pending_response(
46 self.id,
47 FetchResponseMsg::ProcessResponse(request_id, metadata),
48 );
49 }
50
51 fn process_response_chunk(
52 &mut self,
53 _: &mut js::context::JSContext,
54 request_id: RequestId,
55 payload: Bytes,
56 ) {
57 self.cache.notify_pending_response(
58 self.id,
59 FetchResponseMsg::ProcessResponseChunk(request_id, payload),
60 );
61 }
62
63 fn process_response_eof(
64 self,
65 cx: &mut js::context::JSContext,
66 request_id: RequestId,
67 response: Result<(), NetworkError>,
68 timing: ResourceFetchTiming,
69 ) {
70 self.cache.notify_pending_response(
71 self.id,
72 FetchResponseMsg::ProcessResponseEOF(request_id, response.clone(), timing.clone()),
73 );
74 network_listener::submit_timing(cx, &self, &response, &timing);
75 self.doc.root().finish_load(LoadType::Image(self.url), cx);
76 }
77
78 fn process_csp_violations(
79 &mut self,
80 cx: &mut js::context::JSContext,
81 _request_id: RequestId,
82 violations: Vec<Violation>,
83 ) {
84 let global = &self.resource_timing_global();
85 global.report_csp_violations(cx, violations, None, None);
86 }
87
88 fn process_content_length(&mut self, request_id: RequestId, size: usize) {
89 self.cache.notify_pending_response(
90 self.id,
91 FetchResponseMsg::ProcessContentLength(request_id, size),
92 );
93 }
94}
95
96impl ResourceTimingListener for LayoutImageContext {
97 fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
98 (InitiatorType::Css, self.url.clone())
99 }
100
101 fn resource_timing_global(&self) -> DomRoot<GlobalScope> {
102 self.doc.root().global()
103 }
104}
105
106pub(crate) fn fetch_image_for_layout(
107 url: ServoUrl,
108 node: &Node,
109 id: PendingImageId,
110 is_internal_request: InternalRequest,
111 cache: Arc<dyn ImageCache>,
112) {
113 let document = node.owner_document();
114 let context = LayoutImageContext {
115 id,
116 cache,
117 doc: Trusted::new(&document),
118 url: url.clone(),
119 };
120
121 let global = node.owner_global();
122 let request = RequestBuilder::new(
123 Some(document.webview_id()),
124 UrlWithBlobClaim::from_url_without_having_claimed_blob(url.clone()),
125 global.get_referrer(),
126 )
127 .destination(Destination::Image)
128 .is_internal_request(is_internal_request)
129 .with_global_scope(&global);
130
131 document.fetch_blocking(LoadType::Image(url), request, context);
136}