mirror of
https://github.com/servo/servo
synced 2026-04-25 17:15:48 +02:00
This PR refactors parts of the net crate with one minor functional change. Most of the main functions in the net crate are quite long and rather unwieldly. This PR tries to help make them more understandable. - Split parts of obtain_response to have the Router callback setup in another function. - Move functions related to devtools into another file. - Add some servo_tracing. - http_network_or_cache_fetch has another function for append_cache_data to headers. - One functional change: previously in obtain_response, we used the encoded_url via copies and multiple replace calls. We now use the percent_encode crate which is already included in content_security_policy to do this a bit more efficiently. In practice the compiler probably fixed the multiple copies but this is more straightforward. The output should be identical. Testing: As this is mostly a refactor compilation is the test. The percent_encode change is tested in multiple unit tests. --------- Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
196 lines
6.1 KiB
Rust
196 lines
6.1 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
|
|
|
use crossbeam_channel::Sender;
|
|
use devtools_traits::{
|
|
ChromeToDevtoolsControlMsg, DevtoolsControlMsg, HttpRequest as DevtoolsHttpRequest,
|
|
HttpResponse as DevtoolsHttpResponse, NetworkEvent, SecurityInfoUpdate,
|
|
};
|
|
use http::{HeaderMap, Method};
|
|
use hyper_serde::Serde;
|
|
use log::error;
|
|
use net_traits::http_status::HttpStatus;
|
|
use net_traits::request::{Destination, Request};
|
|
use net_traits::response::{CacheState, Response};
|
|
use net_traits::{DebugVec, FetchMetadata};
|
|
use servo_base::id::{BrowsingContextId, PipelineId};
|
|
use servo_url::ServoUrl;
|
|
|
|
use crate::fetch::methods::FetchContext;
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
pub(crate) fn prepare_devtools_request(
|
|
request_id: String,
|
|
url: ServoUrl,
|
|
method: Method,
|
|
headers: HeaderMap,
|
|
body: Option<Vec<u8>>,
|
|
pipeline_id: PipelineId,
|
|
connect_time: Duration,
|
|
send_time: Duration,
|
|
destination: Destination,
|
|
is_xhr: bool,
|
|
browsing_context_id: BrowsingContextId,
|
|
) -> ChromeToDevtoolsControlMsg {
|
|
let started_date_time = SystemTime::now();
|
|
let request = DevtoolsHttpRequest {
|
|
url,
|
|
method,
|
|
headers,
|
|
body: body.map(DebugVec::from),
|
|
pipeline_id,
|
|
started_date_time,
|
|
time_stamp: started_date_time
|
|
.duration_since(UNIX_EPOCH)
|
|
.unwrap_or_default()
|
|
.as_secs() as i64,
|
|
connect_time,
|
|
send_time,
|
|
destination,
|
|
is_xhr,
|
|
browsing_context_id,
|
|
};
|
|
let net_event = NetworkEvent::HttpRequestUpdate(request);
|
|
|
|
ChromeToDevtoolsControlMsg::NetworkEvent(request_id, net_event)
|
|
}
|
|
|
|
pub(crate) fn send_request_to_devtools(
|
|
msg: ChromeToDevtoolsControlMsg,
|
|
devtools_chan: &Sender<DevtoolsControlMsg>,
|
|
) {
|
|
if matches!(msg, ChromeToDevtoolsControlMsg::NetworkEvent(_, ref network_event) if !network_event.forward_to_devtools())
|
|
{
|
|
return;
|
|
}
|
|
if let Err(e) = devtools_chan.send(DevtoolsControlMsg::FromChrome(msg)) {
|
|
error!("DevTools send failed: {e}");
|
|
}
|
|
}
|
|
|
|
pub(crate) fn send_response_to_devtools(
|
|
request: &Request,
|
|
context: &FetchContext,
|
|
response: &Response,
|
|
body_data: Option<Vec<u8>>,
|
|
) {
|
|
let meta = match response.metadata() {
|
|
Ok(FetchMetadata::Unfiltered(m)) => m,
|
|
Ok(FetchMetadata::Filtered { unsafe_, .. }) => unsafe_,
|
|
Err(_) => {
|
|
log::warn!("No metadata available, skipping devtools response.");
|
|
return;
|
|
},
|
|
};
|
|
send_response_values_to_devtools(
|
|
meta.headers.map(Serde::into_inner),
|
|
meta.status,
|
|
body_data,
|
|
response.cache_state,
|
|
request,
|
|
context.devtools_chan.clone(),
|
|
);
|
|
}
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
pub(crate) fn send_response_values_to_devtools(
|
|
headers: Option<HeaderMap>,
|
|
status: HttpStatus,
|
|
body: Option<Vec<u8>>,
|
|
cache_state: CacheState,
|
|
request: &Request,
|
|
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
|
) {
|
|
if let (Some(devtools_chan), Some(pipeline_id), Some(webview_id)) = (
|
|
devtools_chan,
|
|
request.pipeline_id,
|
|
request.target_webview_id,
|
|
) {
|
|
let browsing_context_id = webview_id.into();
|
|
let from_cache = matches!(cache_state, CacheState::Local | CacheState::Validated);
|
|
|
|
let devtoolsresponse = DevtoolsHttpResponse {
|
|
headers,
|
|
status,
|
|
body: body.map(DebugVec::from),
|
|
from_cache,
|
|
pipeline_id,
|
|
browsing_context_id,
|
|
};
|
|
let net_event_response = NetworkEvent::HttpResponse(devtoolsresponse);
|
|
|
|
let msg =
|
|
ChromeToDevtoolsControlMsg::NetworkEvent(request.id.0.to_string(), net_event_response);
|
|
|
|
let _ = devtools_chan.send(DevtoolsControlMsg::FromChrome(msg));
|
|
}
|
|
}
|
|
|
|
pub(crate) fn send_security_info_to_devtools(
|
|
request: &Request,
|
|
context: &FetchContext,
|
|
response: &Response,
|
|
) {
|
|
let meta = match response.metadata() {
|
|
Ok(FetchMetadata::Unfiltered(m)) => m,
|
|
Ok(FetchMetadata::Filtered { unsafe_, .. }) => unsafe_,
|
|
Err(_) => {
|
|
log::warn!("No metadata available, skipping devtools security info.");
|
|
return;
|
|
},
|
|
};
|
|
|
|
if let (Some(devtools_chan), Some(security_info), Some(webview_id)) = (
|
|
context.devtools_chan.clone(),
|
|
meta.tls_security_info,
|
|
request.target_webview_id,
|
|
) {
|
|
let update = NetworkEvent::SecurityInfo(SecurityInfoUpdate {
|
|
browsing_context_id: webview_id.into(),
|
|
security_info: Some(security_info),
|
|
});
|
|
|
|
let msg = ChromeToDevtoolsControlMsg::NetworkEvent(request.id.0.to_string(), update);
|
|
|
|
let _ = devtools_chan.send(DevtoolsControlMsg::FromChrome(msg));
|
|
}
|
|
}
|
|
|
|
pub(crate) fn send_early_httprequest_to_devtools(request: &Request, context: &FetchContext) {
|
|
// Do not forward data requests to devtools
|
|
if request.url().scheme() == "data" {
|
|
return;
|
|
}
|
|
if let (Some(devtools_chan), Some(browsing_context_id), Some(pipeline_id)) = (
|
|
context.devtools_chan.as_ref(),
|
|
request.target_webview_id.map(|id| id.into()),
|
|
request.pipeline_id,
|
|
) {
|
|
// Build the partial DevtoolsHttpRequest
|
|
let devtools_request = DevtoolsHttpRequest {
|
|
url: request.current_url(),
|
|
method: request.method.clone(),
|
|
headers: request.headers.clone(),
|
|
body: None,
|
|
pipeline_id,
|
|
started_date_time: SystemTime::now(),
|
|
time_stamp: 0,
|
|
connect_time: Duration::from_millis(0),
|
|
send_time: Duration::from_millis(0),
|
|
destination: request.destination,
|
|
is_xhr: false,
|
|
browsing_context_id,
|
|
};
|
|
|
|
let msg = ChromeToDevtoolsControlMsg::NetworkEvent(
|
|
request.id.0.to_string(),
|
|
NetworkEvent::HttpRequest(devtools_request),
|
|
);
|
|
|
|
send_request_to_devtools(msg, devtools_chan);
|
|
}
|
|
}
|