net/
request_interceptor.rs1use content_security_policy::Destination;
6use embedder_traits::{GenericEmbedderProxy, WebResourceRequest, WebResourceResponseMsg};
7use log::error;
8use net_traits::http_status::HttpStatus;
9use net_traits::request::Request;
10use net_traits::response::{Response, ResponseBody};
11use net_traits::{NetworkError, ResourceFetchTimingContainer};
12
13use crate::embedder::NetToEmbedderMsg;
14
15#[derive(Clone)]
16pub struct RequestInterceptor {
17 embedder_proxy: GenericEmbedderProxy<NetToEmbedderMsg>,
18}
19
20impl RequestInterceptor {
21 pub fn new(embedder_proxy: GenericEmbedderProxy<NetToEmbedderMsg>) -> RequestInterceptor {
22 RequestInterceptor { embedder_proxy }
23 }
24
25 pub(crate) async fn intercept_request(
26 &self,
27 request: &mut Request,
28 response: &mut Option<Response>,
29 timing_info: &ResourceFetchTimingContainer,
30 ) {
31 let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel();
32 let is_for_main_frame = matches!(request.destination, Destination::Document);
33 let web_resource_request = WebResourceRequest {
34 method: request.method.clone(),
35 url: request.url(),
36 headers: request.headers.clone(),
37 destination: request.destination,
38 referrer_url: request.referrer.to_url().cloned(),
39 is_for_main_frame,
40 is_redirect: request.redirect_count > 0,
41 };
42
43 self.embedder_proxy
44 .send(NetToEmbedderMsg::WebResourceRequested(
45 request.target_webview_id,
46 web_resource_request,
47 sender,
48 ));
49
50 let mut accumulated_body = Vec::new();
52 while let Some(message) = receiver.recv().await {
53 match message {
54 WebResourceResponseMsg::Start(webresource_response) => {
55 let timing = timing_info.inner().clone();
56 let mut response_override =
57 Response::new(webresource_response.url.into(), timing);
58 response_override.headers = webresource_response.headers;
59 response_override.status = HttpStatus::new(
60 webresource_response.status_code,
61 webresource_response.status_message,
62 );
63 *response = Some(response_override);
64 },
65 WebResourceResponseMsg::SendBodyData(data) => {
66 accumulated_body.push(data);
67 },
68 WebResourceResponseMsg::FinishLoad => {
69 if accumulated_body.is_empty() {
70 break;
71 }
72 let Some(response) = response.as_mut() else {
73 error!("Received unexpected FinishLoad message");
74 break;
75 };
76 *response.body.lock() =
77 ResponseBody::Done(accumulated_body.into_iter().flatten().collect());
78 break;
79 },
80 WebResourceResponseMsg::CancelLoad => {
81 *response = Some(Response::network_error(NetworkError::LoadCancelled));
82 break;
83 },
84 WebResourceResponseMsg::DoNotIntercept => break,
85 }
86 }
87 }
88}