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::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::event_loop::document_loader::LoadType;
25use crate::fetch::fetch::RequestWithGlobalScope;
26use crate::fetch::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, _: &GlobalScope, _: RequestId) {}
37 fn process_response(
38 &mut self,
39 _: &mut js::context::JSContext,
40 _: &GlobalScope,
41 request_id: RequestId,
42 metadata: Result<FetchMetadata, NetworkError>,
43 ) {
44 self.cache.notify_pending_response(
45 self.id,
46 FetchResponseMsg::ProcessResponse(request_id, metadata),
47 );
48 }
49
50 fn process_response_chunk(
51 &mut self,
52 _: &mut js::context::JSContext,
53 _: &GlobalScope,
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 global: &GlobalScope,
67 request_id: RequestId,
68 response: Result<(), NetworkError>,
69 timing: ResourceFetchTiming,
70 ) {
71 self.cache.notify_pending_response(
72 self.id,
73 FetchResponseMsg::ProcessResponseEOF(request_id, response.clone(), timing.clone()),
74 );
75 network_listener::submit_timing(cx, global, &self, &response, &timing);
76 self.doc.root().finish_load(LoadType::Image(self.url), cx);
77 }
78
79 fn process_csp_violations(
80 &mut self,
81 cx: &mut js::context::JSContext,
82 global: &GlobalScope,
83 _request_id: RequestId,
84 violations: Vec<Violation>,
85 ) {
86 global.report_csp_violations(cx, violations, None, None);
87 }
88
89 fn process_content_length(&mut self, request_id: RequestId, size: usize) {
90 self.cache.notify_pending_response(
91 self.id,
92 FetchResponseMsg::ProcessContentLength(request_id, size),
93 );
94 }
95}
96
97impl ResourceTimingListener for LayoutImageContext {
98 fn resource_timing_information(&self) -> (InitiatorType, ServoUrl) {
99 (InitiatorType::Css, self.url.clone())
100 }
101}
102
103pub(crate) fn fetch_image_for_layout(
104 url: ServoUrl,
105 node: &Node,
106 id: PendingImageId,
107 is_internal_request: InternalRequest,
108 cache: Arc<dyn ImageCache>,
109) {
110 let document = node.owner_document();
111 let context = LayoutImageContext {
112 id,
113 cache,
114 doc: Trusted::new(&document),
115 url: url.clone(),
116 };
117
118 let global = node.owner_global();
119 let request = RequestBuilder::new(
120 Some(document.webview_id()),
121 UrlWithBlobClaim::from_url_without_having_claimed_blob(url.clone()),
122 global.get_referrer(),
123 )
124 .destination(Destination::Image)
125 .is_internal_request(is_internal_request)
126 .with_global_scope(&global);
127
128 document.fetch_blocking(LoadType::Image(url), request, context);
133}