mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
script: Move navigation fetching to the ScriptThread
(#34919)
This allows reusing the asynchrnous fetch mechanism that we use for page resources and is likely a step toward removing the `FetchThread`. Benefits: - Reduces IPC traffic during navigation. Now instead of bouncing between the constellation and the `ScriptThread` responses are sent directly to the `ScriptThread`. - Allows cancelling loads after redirects, which was not possible before. There is the question of what to do when a redirect is cross-origin (#23037). This currently isn't handled properly as the `Constellation` sends data to the same `Pipeline` that initiated the load. This change doesn't fix this issue, but does make it more possible for the `ScriptThread` to shut down the pipeline and ask the `Constellation` to replace it with a new one. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
73c0701c83
commit
fbd77b4524
16 changed files with 420 additions and 460 deletions
|
@ -14,7 +14,7 @@ use base::id::HistoryStateId;
|
|||
use cookie::Cookie;
|
||||
use crossbeam_channel::{unbounded, Receiver, Sender};
|
||||
use headers::{ContentType, HeaderMapExt, ReferrerPolicy as ReferrerPolicyHeader};
|
||||
use http::{Error as HttpError, HeaderMap, StatusCode};
|
||||
use http::{header, Error as HttpError, HeaderMap, HeaderValue, StatusCode};
|
||||
use hyper_serde::Serde;
|
||||
use hyper_util::client::legacy::Error as HyperError;
|
||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||
|
@ -46,6 +46,10 @@ pub mod request;
|
|||
pub mod response;
|
||||
pub mod storage_thread;
|
||||
|
||||
/// <https://fetch.spec.whatwg.org/#document-accept-header-value>
|
||||
pub const DOCUMENT_ACCEPT_HEADER_VALUE: HeaderValue =
|
||||
HeaderValue::from_static("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
||||
|
||||
/// An implementation of the [Fetch specification](https://fetch.spec.whatwg.org/)
|
||||
pub mod fetch {
|
||||
pub mod headers;
|
||||
|
@ -197,7 +201,7 @@ pub enum FetchResponseMsg {
|
|||
}
|
||||
|
||||
impl FetchResponseMsg {
|
||||
fn request_id(&self) -> RequestId {
|
||||
pub fn request_id(&self) -> RequestId {
|
||||
match self {
|
||||
FetchResponseMsg::ProcessRequestBody(id) |
|
||||
FetchResponseMsg::ProcessRequestEOF(id) |
|
||||
|
@ -252,6 +256,15 @@ pub enum FetchMetadata {
|
|||
},
|
||||
}
|
||||
|
||||
impl FetchMetadata {
|
||||
pub fn metadata(&self) -> &Metadata {
|
||||
match self {
|
||||
Self::Unfiltered(metadata) => metadata,
|
||||
Self::Filtered { unsafe_, .. } => unsafe_,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FetchResponseListener {
|
||||
fn process_request_body(&mut self, request_id: RequestId);
|
||||
fn process_request_eof(&mut self, request_id: RequestId);
|
||||
|
@ -511,6 +524,7 @@ pub enum CoreResourceMsg {
|
|||
enum ToFetchThreadMessage {
|
||||
StartFetch(
|
||||
/* request_builder */ RequestBuilder,
|
||||
/* response_init */ Option<ResponseInit>,
|
||||
/* cancel_chan */ Option<IpcReceiver<()>>,
|
||||
/* callback */ BoxedFetchCallback,
|
||||
),
|
||||
|
@ -570,14 +584,29 @@ impl FetchThread {
|
|||
fn run(&mut self) {
|
||||
loop {
|
||||
match self.receiver.recv().unwrap() {
|
||||
ToFetchThreadMessage::StartFetch(request_builder, canceller, callback) => {
|
||||
ToFetchThreadMessage::StartFetch(
|
||||
request_builder,
|
||||
response_init,
|
||||
canceller,
|
||||
callback,
|
||||
) => {
|
||||
self.active_fetches.insert(request_builder.id, callback);
|
||||
self.core_resource_thread
|
||||
.send(CoreResourceMsg::Fetch(
|
||||
|
||||
// Only redirects have a `response_init` field.
|
||||
let message = match response_init {
|
||||
Some(response_init) => CoreResourceMsg::FetchRedirect(
|
||||
request_builder,
|
||||
response_init,
|
||||
self.to_fetch_sender.clone(),
|
||||
canceller,
|
||||
),
|
||||
None => CoreResourceMsg::Fetch(
|
||||
request_builder,
|
||||
FetchChannels::ResponseMsg(self.to_fetch_sender.clone(), canceller),
|
||||
))
|
||||
.unwrap();
|
||||
),
|
||||
};
|
||||
|
||||
self.core_resource_thread.send(message).unwrap();
|
||||
},
|
||||
ToFetchThreadMessage::FetchResponse(fetch_response_msg) => {
|
||||
let request_id = fetch_response_msg.request_id();
|
||||
|
@ -599,18 +628,23 @@ impl FetchThread {
|
|||
}
|
||||
}
|
||||
|
||||
/// Instruct the resource thread to make a new request.
|
||||
static FETCH_THREAD: OnceLock<Sender<ToFetchThreadMessage>> = OnceLock::new();
|
||||
|
||||
/// Instruct the resource thread to make a new fetch request.
|
||||
pub fn fetch_async(
|
||||
core_resource_thread: &CoreResourceThread,
|
||||
request: RequestBuilder,
|
||||
response_init: Option<ResponseInit>,
|
||||
canceller: Option<IpcReceiver<()>>,
|
||||
callback: BoxedFetchCallback,
|
||||
) {
|
||||
static FETCH_THREAD: OnceLock<Sender<ToFetchThreadMessage>> = OnceLock::new();
|
||||
let _ = FETCH_THREAD
|
||||
.get_or_init(|| FetchThread::spawn(core_resource_thread))
|
||||
.send(ToFetchThreadMessage::StartFetch(
|
||||
request, canceller, callback,
|
||||
request,
|
||||
response_init,
|
||||
canceller,
|
||||
callback,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -945,5 +979,17 @@ pub fn http_percent_encode(bytes: &[u8]) -> String {
|
|||
percent_encoding::percent_encode(bytes, HTTP_VALUE).to_string()
|
||||
}
|
||||
|
||||
pub fn set_default_accept_language(headers: &mut HeaderMap) {
|
||||
if headers.contains_key(header::ACCEPT_LANGUAGE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(eijebong): Change this once typed headers are done
|
||||
headers.insert(
|
||||
header::ACCEPT_LANGUAGE,
|
||||
HeaderValue::from_static("en-US,en;q=0.5"),
|
||||
);
|
||||
}
|
||||
|
||||
pub static PRIVILEGED_SECRET: LazyLock<u32> =
|
||||
LazyLock::new(|| servo_rand::ServoRng::default().next_u32());
|
||||
|
|
|
@ -47,7 +47,7 @@ use media::WindowGLContext;
|
|||
use net_traits::image_cache::ImageCache;
|
||||
use net_traits::request::{Referrer, RequestBody};
|
||||
use net_traits::storage_thread::StorageType;
|
||||
use net_traits::{FetchResponseMsg, ReferrerPolicy, ResourceThreads};
|
||||
use net_traits::{ReferrerPolicy, ResourceThreads};
|
||||
use pixels::{Image, PixelFormat};
|
||||
use profile_traits::{mem, time as profile_time};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
@ -286,16 +286,12 @@ pub enum UpdatePipelineIdReason {
|
|||
|
||||
/// Messages sent from the constellation or layout to the script thread.
|
||||
// FIXME: https://github.com/servo/servo/issues/34591
|
||||
#[expect(clippy::large_enum_variant)]
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub enum ConstellationControlMsg {
|
||||
/// Takes the associated window proxy out of "delaying-load-events-mode",
|
||||
/// used if a scheduled navigated was refused by the embedder.
|
||||
/// <https://html.spec.whatwg.org/multipage/#delaying-load-events-mode>
|
||||
StopDelayingLoadEventsMode(PipelineId),
|
||||
/// Sends the final response to script thread for fetching after all redirections
|
||||
/// have been resolved
|
||||
NavigationResponse(PipelineId, FetchResponseMsg),
|
||||
/// Gives a channel and ID to a layout, as well as the ID of that layout's parent
|
||||
AttachLayout(NewLayoutInfo),
|
||||
/// Window resized. Sends a DOM event eventually, but first we combine events.
|
||||
|
@ -413,7 +409,6 @@ impl fmt::Debug for ConstellationControlMsg {
|
|||
use self::ConstellationControlMsg::*;
|
||||
let variant = match *self {
|
||||
StopDelayingLoadEventsMode(..) => "StopDelayingLoadsEventMode",
|
||||
NavigationResponse(..) => "NavigationResponse",
|
||||
AttachLayout(..) => "AttachLayout",
|
||||
Resize(..) => "Resize",
|
||||
ThemeChange(..) => "ThemeChange",
|
||||
|
|
|
@ -17,7 +17,6 @@ use embedder_traits::{EmbedderMsg, MediaSessionEvent};
|
|||
use euclid::default::Size2D as UntypedSize2D;
|
||||
use euclid::Size2D;
|
||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||
use net_traits::request::RequestBuilder;
|
||||
use net_traits::storage_thread::StorageType;
|
||||
use net_traits::CoreResourceMsg;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -128,9 +127,6 @@ pub enum ScriptMsg {
|
|||
ScheduleBroadcast(BroadcastChannelRouterId, BroadcastMsg),
|
||||
/// Forward a message to the embedder.
|
||||
ForwardToEmbedder(EmbedderMsg),
|
||||
/// Requests are sent to constellation and fetches are checked manually
|
||||
/// for cross-origin loads
|
||||
InitiateNavigateRequest(RequestBuilder, /* cancellation_chan */ IpcReceiver<()>),
|
||||
/// Broadcast a storage event to every same-origin pipeline.
|
||||
/// The strings are key, old value and new value.
|
||||
BroadcastStorageEvent(
|
||||
|
@ -271,7 +267,6 @@ impl fmt::Debug for ScriptMsg {
|
|||
NewBroadcastChannelNameInRouter(..) => "NewBroadcastChannelNameInRouter",
|
||||
ScheduleBroadcast(..) => "ScheduleBroadcast",
|
||||
ForwardToEmbedder(..) => "ForwardToEmbedder",
|
||||
InitiateNavigateRequest(..) => "InitiateNavigateRequest",
|
||||
BroadcastStorageEvent(..) => "BroadcastStorageEvent",
|
||||
ChangeRunningAnimationsState(..) => "ChangeRunningAnimationsState",
|
||||
CreateCanvasPaintThread(..) => "CreateCanvasPaintThread",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue