diff --git a/Cargo.lock b/Cargo.lock index 5d8e04f5d23..591883b31d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1865,6 +1865,7 @@ dependencies = [ "serde", "servo_malloc_size_of", "servo_url", + "url", "webrender_api", "webxr-api", ] diff --git a/components/malloc_size_of/lib.rs b/components/malloc_size_of/lib.rs index 50d4ce30718..241dba8eba9 100644 --- a/components/malloc_size_of/lib.rs +++ b/components/malloc_size_of/lib.rs @@ -648,6 +648,14 @@ impl MallocSizeOf for url::Host { } } +impl MallocSizeOf for url::Url { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + // TODO: This is an estimate, but a real size should be calculated in `rust-url` once + // it has support for `malloc_size_of`. + self.to_string().size_of(ops) + } +} + impl MallocSizeOf for euclid::Vector2D { fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { self.x.size_of(ops) + self.y.size_of(ops) diff --git a/components/net/fetch/methods.rs b/components/net/fetch/methods.rs index 9990b3f8478..cd23e61d60d 100644 --- a/components/net/fetch/methods.rs +++ b/components/net/fetch/methods.rs @@ -43,7 +43,7 @@ use crate::fetch::headers::determine_nosniff; use crate::filemanager_thread::FileManager; use crate::http_loader::{determine_requests_referrer, http_fetch, set_default_accept, HttpState}; use crate::protocols::ProtocolRegistry; -use crate::request_intercepter::RequestIntercepter; +use crate::request_interceptor::RequestInterceptor; use crate::subresource_integrity::is_response_integrity_valid; pub type Target<'a> = &'a mut (dyn FetchTaskTarget + Send); @@ -61,7 +61,7 @@ pub struct FetchContext { pub devtools_chan: Option>>>, pub filemanager: Arc>, pub file_token: FileTokenCheck, - pub request_intercepter: Arc>, + pub request_interceptor: Arc>, pub cancellation_listener: Arc, pub timing: ServoArc>, pub protocols: Arc, @@ -328,7 +328,7 @@ pub async fn main_fetch( // Intercept the request and maybe override the response. context - .request_intercepter + .request_interceptor .lock() .unwrap() .intercept_request(request, &mut response, context); diff --git a/components/net/lib.rs b/components/net/lib.rs index d97cf1ccd1a..0576c017e59 100644 --- a/components/net/lib.rs +++ b/components/net/lib.rs @@ -18,7 +18,7 @@ pub mod image_cache; pub mod local_directory_listing; pub mod mime_classifier; pub mod protocols; -pub mod request_intercepter; +pub mod request_interceptor; pub mod resource_thread; mod storage_thread; pub mod subresource_integrity; diff --git a/components/net/request_intercepter.rs b/components/net/request_intercepter.rs deleted file mode 100644 index 9ef07fe9f3a..00000000000 --- a/components/net/request_intercepter.rs +++ /dev/null @@ -1,105 +0,0 @@ -/* 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 content_security_policy::Destination; -use embedder_traits::{ - EmbedderMsg, EmbedderProxy, HttpBodyData, WebResourceRequest, WebResourceResponseMsg, -}; -use ipc_channel::ipc; -use net_traits::http_status::HttpStatus; -use net_traits::request::Request; -use net_traits::response::{Response, ResponseBody}; -use net_traits::NetworkError; - -use crate::fetch::methods::FetchContext; - -#[derive(Clone)] -pub struct RequestIntercepter { - embedder_proxy: EmbedderProxy, -} - -impl RequestIntercepter { - pub fn new(embedder_proxy: EmbedderProxy) -> RequestIntercepter { - RequestIntercepter { embedder_proxy } - } - - pub fn intercept_request( - &self, - request: &mut Request, - response: &mut Option, - context: &FetchContext, - ) { - let (tx, rx) = ipc::channel().unwrap(); - let is_for_main_frame = matches!(request.destination, Destination::Document); - let req = WebResourceRequest::new( - request.method.clone(), - request.headers.clone(), - request.url(), - is_for_main_frame, - request.redirect_count > 0, - ); - - self.embedder_proxy.send(EmbedderMsg::WebResourceRequested( - request.target_webview_id, - req, - tx, - )); - let mut response_received = false; - - // TODO: use done_chan and run in CoreResourceThreadPool. - while let Ok(msg) = rx.recv() { - match msg { - WebResourceResponseMsg::Start(webresource_response) => { - response_received = true; - let timing = context.timing.lock().unwrap().clone(); - let mut res = Response::new(webresource_response.url.clone(), timing); - res.headers = webresource_response.headers; - res.status = HttpStatus::new( - webresource_response.status_code, - webresource_response.status_message, - ); - *res.body.lock().unwrap() = ResponseBody::Receiving(Vec::new()); - *response = Some(res); - }, - WebResourceResponseMsg::Body(data) => { - if !response_received { - panic!("Receive body before initializing a Response!"); - } - if let Some(ref mut res) = *response { - match data { - HttpBodyData::Chunk(chunk) => { - if let ResponseBody::Receiving(ref mut body) = - *res.body.lock().unwrap() - { - body.extend_from_slice(&chunk); - } else { - panic!("Receive Playload Message when Response body is not in Receiving state!"); - } - }, - HttpBodyData::Done => { - let mut res_body = res.body.lock().unwrap(); - if let ResponseBody::Receiving(ref mut body) = *res_body { - let completed_body = std::mem::take(body); - *res_body = ResponseBody::Done(completed_body); - } else { - panic!("Receive Done Message when Response body is not in Receiving state!"); - } - break; - }, - HttpBodyData::Cancelled => { - *response = - Some(Response::network_error(NetworkError::LoadCancelled)); - break; - }, - } - } - }, - WebResourceResponseMsg::None => { - // Will not intercept the response. Continue. - break; - }, - } - } - } -} diff --git a/components/net/request_interceptor.rs b/components/net/request_interceptor.rs new file mode 100644 index 00000000000..366f5cd26d0 --- /dev/null +++ b/components/net/request_interceptor.rs @@ -0,0 +1,86 @@ +/* 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 content_security_policy::Destination; +use embedder_traits::{EmbedderMsg, EmbedderProxy, WebResourceRequest, WebResourceResponseMsg}; +use ipc_channel::ipc; +use log::error; +use net_traits::http_status::HttpStatus; +use net_traits::request::Request; +use net_traits::response::{Response, ResponseBody}; +use net_traits::NetworkError; + +use crate::fetch::methods::FetchContext; + +#[derive(Clone)] +pub struct RequestInterceptor { + embedder_proxy: EmbedderProxy, +} + +impl RequestInterceptor { + pub fn new(embedder_proxy: EmbedderProxy) -> RequestInterceptor { + RequestInterceptor { embedder_proxy } + } + + pub fn intercept_request( + &self, + request: &mut Request, + response: &mut Option, + context: &FetchContext, + ) { + let (sender, receiver) = ipc::channel().unwrap(); + let is_for_main_frame = matches!(request.destination, Destination::Document); + let web_resource_request = WebResourceRequest { + method: request.method.clone(), + url: request.url().into_url(), + headers: request.headers.clone(), + is_for_main_frame, + is_redirect: request.redirect_count > 0, + }; + + self.embedder_proxy.send(EmbedderMsg::WebResourceRequested( + request.target_webview_id, + web_resource_request, + sender, + )); + + // TODO: use done_chan and run in CoreResourceThreadPool. + let mut accumulated_body = Vec::new(); + while let Ok(message) = receiver.recv() { + match message { + WebResourceResponseMsg::Start(webresource_response) => { + let timing = context.timing.lock().unwrap().clone(); + let mut response_override = + Response::new(webresource_response.url.into(), timing); + response_override.headers = webresource_response.headers; + response_override.status = HttpStatus::new( + webresource_response.status_code, + webresource_response.status_message, + ); + *response = Some(response_override); + }, + WebResourceResponseMsg::SendBodyData(data) => { + accumulated_body.push(data); + }, + WebResourceResponseMsg::FinishLoad => { + if accumulated_body.is_empty() { + break; + } + let Some(response) = response.as_mut() else { + error!("Received unexpected FinishLoad message"); + break; + }; + *response.body.lock().unwrap() = + ResponseBody::Done(accumulated_body.into_iter().flatten().collect()); + break; + }, + WebResourceResponseMsg::CancelLoad => { + *response = Some(Response::network_error(NetworkError::LoadCancelled)); + break; + }, + WebResourceResponseMsg::DoNotIntercept => break, + } + } + } +} diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs index e16c5f541f3..8306e4049f1 100644 --- a/components/net/resource_thread.rs +++ b/components/net/resource_thread.rs @@ -54,7 +54,7 @@ use crate::hsts::HstsList; use crate::http_cache::HttpCache; use crate::http_loader::{http_redirect_fetch, HttpState}; use crate::protocols::ProtocolRegistry; -use crate::request_intercepter::RequestIntercepter; +use crate::request_interceptor::RequestInterceptor; use crate::storage_thread::StorageThreadFactory; use crate::websocket_loader; @@ -553,7 +553,7 @@ pub struct CoreResourceManager { devtools_sender: Option>, sw_managers: HashMap>, filemanager: FileManager, - request_intercepter: RequestIntercepter, + request_interceptor: RequestInterceptor, thread_pool: Arc, ca_certificates: CACertificates, ignore_certificate_errors: bool, @@ -706,7 +706,7 @@ impl CoreResourceManager { devtools_sender, sw_managers: Default::default(), filemanager: FileManager::new(embedder_proxy.clone(), Arc::downgrade(&pool_handle)), - request_intercepter: RequestIntercepter::new(embedder_proxy), + request_interceptor: RequestInterceptor::new(embedder_proxy), thread_pool: pool_handle, ca_certificates, ignore_certificate_errors, @@ -749,7 +749,7 @@ impl CoreResourceManager { let ua = self.user_agent.clone(); let dc = self.devtools_sender.clone(); let filemanager = self.filemanager.clone(); - let request_intercepter = self.request_intercepter.clone(); + let request_interceptor = self.request_interceptor.clone(); let timing_type = match request_builder.destination { Destination::Document => ResourceTimingType::Navigation, @@ -791,7 +791,7 @@ impl CoreResourceManager { devtools_chan: dc.map(|dc| Arc::new(Mutex::new(dc))), filemanager: Arc::new(Mutex::new(filemanager)), file_token, - request_intercepter: Arc::new(Mutex::new(request_intercepter)), + request_interceptor: Arc::new(Mutex::new(request_interceptor)), cancellation_listener, timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new(request.timing_type()))), protocols, diff --git a/components/net/tests/fetch.rs b/components/net/tests/fetch.rs index b5af2b640d5..27fff40e897 100644 --- a/components/net/tests/fetch.rs +++ b/components/net/tests/fetch.rs @@ -30,7 +30,7 @@ use net::fetch::methods::{self, FetchContext}; use net::filemanager_thread::FileManager; use net::hsts::HstsEntry; use net::protocols::ProtocolRegistry; -use net::request_intercepter::RequestIntercepter; +use net::request_interceptor::RequestInterceptor; use net::resource_thread::CoreResourceThreadPool; use net_traits::filemanager_thread::FileTokenCheck; use net_traits::http_status::HttpStatus; @@ -708,7 +708,7 @@ fn test_fetch_with_hsts() { Weak::new(), ))), file_token: FileTokenCheck::NotRequired, - request_intercepter: Arc::new(Mutex::new(RequestIntercepter::new(embedder_proxy))), + request_interceptor: Arc::new(Mutex::new(RequestInterceptor::new(embedder_proxy))), cancellation_listener: Arc::new(Default::default()), timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new( ResourceTimingType::Navigation, @@ -768,7 +768,7 @@ fn test_load_adds_host_to_hsts_list_when_url_is_https() { Weak::new(), ))), file_token: FileTokenCheck::NotRequired, - request_intercepter: Arc::new(Mutex::new(RequestIntercepter::new(embedder_proxy))), + request_interceptor: Arc::new(Mutex::new(RequestInterceptor::new(embedder_proxy))), cancellation_listener: Arc::new(Default::default()), timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new( ResourceTimingType::Navigation, @@ -830,7 +830,7 @@ fn test_fetch_self_signed() { Weak::new(), ))), file_token: FileTokenCheck::NotRequired, - request_intercepter: Arc::new(Mutex::new(RequestIntercepter::new(embedder_proxy))), + request_interceptor: Arc::new(Mutex::new(RequestInterceptor::new(embedder_proxy))), cancellation_listener: Arc::new(Default::default()), timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new( ResourceTimingType::Navigation, @@ -1363,17 +1363,13 @@ fn test_fetch_request_intercepted() { .status_message(STATUS_MESSAGE.to_vec()); let msg = embedder_traits::WebResourceResponseMsg::Start(response); let _ = response_sender.send(msg); - let msg2 = embedder_traits::WebResourceResponseMsg::Body( - embedder_traits::HttpBodyData::Chunk(BODY_PART1.to_vec()), - ); + let msg2 = + embedder_traits::WebResourceResponseMsg::SendBodyData(BODY_PART1.to_vec()); let _ = response_sender.send(msg2); - let msg3 = embedder_traits::WebResourceResponseMsg::Body( - embedder_traits::HttpBodyData::Chunk(BODY_PART2.to_vec()), - ); + let msg3 = + embedder_traits::WebResourceResponseMsg::SendBodyData(BODY_PART2.to_vec()); let _ = response_sender.send(msg3); - let _ = response_sender.send(embedder_traits::WebResourceResponseMsg::Body( - embedder_traits::HttpBodyData::Done, - )); + let _ = response_sender.send(embedder_traits::WebResourceResponseMsg::FinishLoad); }, _ => unreachable!(), } @@ -1388,7 +1384,7 @@ fn test_fetch_request_intercepted() { Weak::new(), ))), file_token: FileTokenCheck::NotRequired, - request_intercepter: Arc::new(Mutex::new(RequestIntercepter::new(embedder_proxy))), + request_interceptor: Arc::new(Mutex::new(RequestInterceptor::new(embedder_proxy))), cancellation_listener: Arc::new(Default::default()), timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new( ResourceTimingType::Navigation, diff --git a/components/net/tests/main.rs b/components/net/tests/main.rs index 99bb918091a..531fefb1eb0 100644 --- a/components/net/tests/main.rs +++ b/components/net/tests/main.rs @@ -42,7 +42,7 @@ use net::fetch::cors_cache::CorsCache; use net::fetch::methods::{self, FetchContext}; use net::filemanager_thread::FileManager; use net::protocols::ProtocolRegistry; -use net::request_intercepter::RequestIntercepter; +use net::request_interceptor::RequestInterceptor; use net::resource_thread::CoreResourceThreadPool; use net::test::HttpState; use net_traits::filemanager_thread::FileTokenCheck; @@ -177,7 +177,7 @@ fn new_fetch_context( pool_handle.unwrap_or_else(|| Weak::new()), ))), file_token: FileTokenCheck::NotRequired, - request_intercepter: Arc::new(Mutex::new(RequestIntercepter::new(sender))), + request_interceptor: Arc::new(Mutex::new(RequestInterceptor::new(sender))), cancellation_listener: Arc::new(Default::default()), timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new( ResourceTimingType::Navigation, diff --git a/components/servo/lib.rs b/components/servo/lib.rs index cabc2c40295..26ab938982f 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -126,7 +126,7 @@ pub use crate::servo_delegate::{ServoDelegate, ServoError}; pub use crate::webview::WebView; pub use crate::webview_delegate::{ AllowOrDenyRequest, AuthenticationRequest, NavigationRequest, PermissionRequest, - WebViewDelegate, + WebResourceLoad, WebViewDelegate, }; #[cfg(feature = "webdriver")] @@ -836,20 +836,17 @@ impl Servo { web_resource_request, response_sender, ) => { - let webview = webview_id.and_then(|webview_id| self.get_webview_handle(webview_id)); - if let Some(webview) = webview.clone() { - webview.delegate().intercept_web_resource_load( - webview, - &web_resource_request, - response_sender.clone(), - ); - } - - self.delegate().intercept_web_resource_load( - webview, - &web_resource_request, + let web_resource_load = WebResourceLoad { + request: web_resource_request, response_sender, - ); + intercepted: false, + }; + match webview_id.and_then(|webview_id| self.get_webview_handle(webview_id)) { + Some(webview) => webview + .delegate() + .load_web_resource(webview, web_resource_load), + None => self.delegate().load_web_resource(web_resource_load), + } }, EmbedderMsg::Panic(webview_id, reason, backtrace) => { if let Some(webview) = self.get_webview_handle(webview_id) { diff --git a/components/servo/servo_delegate.rs b/components/servo/servo_delegate.rs index 379be8a8513..3c2b9befaaa 100644 --- a/components/servo/servo_delegate.rs +++ b/components/servo/servo_delegate.rs @@ -2,11 +2,8 @@ * 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 embedder_traits::{WebResourceRequest, WebResourceResponseMsg}; -use ipc_channel::ipc::IpcSender; - -use crate::webview_delegate::AllowOrDenyRequest; -use crate::{Servo, WebView}; +use crate::webview_delegate::{AllowOrDenyRequest, WebResourceLoad}; +use crate::Servo; #[derive(Clone, Copy, Debug, Hash, PartialEq)] pub enum ServoError { @@ -27,20 +24,14 @@ pub trait ServoDelegate { /// Request a DevTools connection from a DevTools client. Typically an embedder application /// will show a permissions prompt when this happens to confirm a connection is allowed. fn request_devtools_connection(&self, _servo: &Servo, _request: AllowOrDenyRequest) {} - /// Potentially intercept a resource request. If not handled, the request will not be intercepted. + /// Triggered when Servo will load a web (HTTP/HTTPS) resource. The load may be + /// intercepted and alternate contents can be loaded by the client by calling + /// [`WebResourceLoad::intercept`]. If not handled, the load will continue as normal. /// - /// Note: If this request is associated with a `WebView`, the `WebViewDelegate` will - /// receive this notification first and have a chance to intercept the request. - /// - /// TODO: This API needs to be reworked to match the new model of how responses are sent. - fn intercept_web_resource_load( - &self, - _webview: Option, - _request: &WebResourceRequest, - response_sender: IpcSender, - ) { - let _ = response_sender.send(WebResourceResponseMsg::None); - } + /// Note: This delegate method is called for all resource loads not associated with a + /// [`WebView`]. For loads associated with a [`WebView`], Servo will call + /// [`crate::WebViewDelegate::load_web_resource`]. + fn load_web_resource(&self, _load: WebResourceLoad) {} } pub(crate) struct DefaultServoDelegate; diff --git a/components/servo/webview_delegate.rs b/components/servo/webview_delegate.rs index c84ef699647..ef8cb93cb66 100644 --- a/components/servo/webview_delegate.rs +++ b/components/servo/webview_delegate.rs @@ -9,7 +9,8 @@ use compositing_traits::ConstellationMsg; use embedder_traits::{ AllowOrDeny, AuthenticationResponse, ContextMenuResult, Cursor, FilterPattern, GamepadHapticEffectType, InputMethodType, LoadStatus, MediaSessionEvent, PermissionFeature, - PromptDefinition, PromptOrigin, WebResourceRequest, WebResourceResponseMsg, + PromptDefinition, PromptOrigin, WebResourceRequest, WebResourceResponse, + WebResourceResponseMsg, }; use ipc_channel::ipc::IpcSender; use keyboard_types::KeyboardEvent; @@ -143,6 +144,90 @@ impl Drop for AuthenticationRequest { } } +/// Information related to the loading of a web resource. These are created for all HTTP requests. +/// The client may choose to intercept the load of web resources and send an alternate response +/// by calling [`WebResourceLoad::intercept`]. +pub struct WebResourceLoad { + pub request: WebResourceRequest, + pub(crate) response_sender: IpcSender, + pub(crate) intercepted: bool, +} + +impl WebResourceLoad { + /// The [`WebResourceRequest`] associated with this [`WebResourceLoad`]. + pub fn request(&self) -> &WebResourceRequest { + &self.request + } + /// Intercept this [`WebResourceLoad`] and control the response via the returned + /// [`InterceptedWebResourceLoad`]. + pub fn intercept(mut self, response: WebResourceResponse) -> InterceptedWebResourceLoad { + let _ = self + .response_sender + .send(WebResourceResponseMsg::Start(response)); + self.intercepted = true; + InterceptedWebResourceLoad { + request: self.request.clone(), + response_sender: self.response_sender.clone(), + finished: false, + } + } +} + +impl Drop for WebResourceLoad { + fn drop(&mut self) { + if !self.intercepted { + let _ = self + .response_sender + .send(WebResourceResponseMsg::DoNotIntercept); + } + } +} + +/// An intercepted web resource load. This struct allows the client to send an alternative response +/// after calling [`WebResourceLoad::intercept`]. In order to send chunks of body data, the client +/// must call [`InterceptedWebResourceLoad::send_body_data`]. When the interception is complete, the client +/// should call [`InterceptedWebResourceLoad::finish`]. If neither `finish()` or `cancel()` are called, +/// this interception will automatically be finished when dropped. +pub struct InterceptedWebResourceLoad { + pub request: WebResourceRequest, + pub(crate) response_sender: IpcSender, + pub(crate) finished: bool, +} + +impl InterceptedWebResourceLoad { + /// Send a chunk of response body data. It's possible to make subsequent calls to + /// this method when streaming body data. + pub fn send_body_data(&self, data: Vec) { + let _ = self + .response_sender + .send(WebResourceResponseMsg::SendBodyData(data)); + } + /// Finish this [`InterceptedWebResourceLoad`] and complete the response. + pub fn finish(mut self) { + let _ = self + .response_sender + .send(WebResourceResponseMsg::FinishLoad); + self.finished = true; + } + /// Cancel this [`InterceptedWebResourceLoad`], which will trigger a network error. + pub fn cancel(mut self) { + let _ = self + .response_sender + .send(WebResourceResponseMsg::CancelLoad); + self.finished = true; + } +} + +impl Drop for InterceptedWebResourceLoad { + fn drop(&mut self) { + if !self.finished { + let _ = self + .response_sender + .send(WebResourceResponseMsg::FinishLoad); + } + } +} + pub trait WebViewDelegate { /// The URL of the currently loaded page in this [`WebView`] has changed. The new /// URL can accessed via [`WebView::url`]. @@ -296,19 +381,14 @@ pub trait WebViewDelegate { /// Request to stop a haptic effect on a connected gamepad. fn stop_gamepad_haptic_effect(&self, _webview: WebView, _: usize, _: IpcSender) {} - /// Potentially intercept a resource request. If not handled, the request will not be intercepted. + /// Triggered when this [`WebView`] will load a web (HTTP/HTTPS) resource. The load may be + /// intercepted and alternate contents can be loaded by the client by calling + /// [`WebResourceLoad::intercept`]. If not handled, the load will continue as normal. /// - /// Note: The `ServoDelegate` will also receive this notification and have a chance to intercept - /// the request. - /// - /// TODO: This API needs to be reworked to match the new model of how responses are sent. - fn intercept_web_resource_load( - &self, - _webview: WebView, - _request: &WebResourceRequest, - _response_sender: IpcSender, - ) { - } + /// Note: This delegate method is called for all resource loads associated with a [`WebView`]. + /// For loads not associated with a [`WebView`], such as those for service workers, Servo + /// will call [`crate::ServoDelegate::load_web_resource`]. + fn load_web_resource(&self, _webview: WebView, _load: WebResourceLoad) {} } pub(crate) struct DefaultWebViewDelegate; diff --git a/components/shared/embedder/Cargo.toml b/components/shared/embedder/Cargo.toml index 3076d1c4896..3bb8a5ee83c 100644 --- a/components/shared/embedder/Cargo.toml +++ b/components/shared/embedder/Cargo.toml @@ -30,5 +30,6 @@ malloc_size_of_derive = { workspace = true } num-traits = { workspace = true } serde = { workspace = true } servo_url = { path = "../../url" } +url = { workspace = true } webrender_api = { workspace = true } webxr-api = { workspace = true, features = ["ipc"], optional = true } diff --git a/components/shared/embedder/lib.rs b/components/shared/embedder/lib.rs index 533826408c1..071ad16be71 100644 --- a/components/shared/embedder/lib.rs +++ b/components/shared/embedder/lib.rs @@ -18,6 +18,7 @@ use malloc_size_of_derive::MallocSizeOf; use num_derive::FromPrimitive; use serde::{Deserialize, Serialize}; use servo_url::ServoUrl; +use url::Url; use webrender_api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize}; pub use crate::input_events::*; @@ -452,49 +453,30 @@ pub struct WebResourceRequest { )] #[ignore_malloc_size_of = "Defined in hyper"] pub headers: HeaderMap, - pub url: ServoUrl, + pub url: Url, pub is_for_main_frame: bool, pub is_redirect: bool, } -impl WebResourceRequest { - pub fn new( - method: Method, - headers: HeaderMap, - url: ServoUrl, - is_for_main_frame: bool, - is_redirect: bool, - ) -> Self { - WebResourceRequest { - method, - url, - headers, - is_for_main_frame, - is_redirect, - } - } -} - #[derive(Clone, Deserialize, Serialize)] pub enum WebResourceResponseMsg { - // Response of WebResourceRequest, no body included. + /// Start an interception of this web resource load. It's expected that the client subsequently + /// send either a `CancelLoad` or `FinishLoad` message after optionally sending chunks of body + /// data via `SendBodyData`. Start(WebResourceResponse), - // send a body chunk. It is expected Response sent before body. - Body(HttpBodyData), - // not to override the response. - None, -} - -#[derive(Clone, Deserialize, Serialize)] -pub enum HttpBodyData { - Chunk(Vec), - Done, - Cancelled, + /// Send a chunk of body data. + SendBodyData(Vec), + /// Signal that this load has been finished by the interceptor. + FinishLoad, + /// Signal that this load has been cancelled by the interceptor. + CancelLoad, + /// Signal that this load will not be intercepted. + DoNotIntercept, } #[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)] pub struct WebResourceResponse { - pub url: ServoUrl, + pub url: Url, #[serde( deserialize_with = "::hyper_serde::deserialize", serialize_with = "::hyper_serde::serialize" @@ -511,7 +493,7 @@ pub struct WebResourceResponse { } impl WebResourceResponse { - pub fn new(url: ServoUrl) -> WebResourceResponse { + pub fn new(url: Url) -> WebResourceResponse { WebResourceResponse { url, headers: HeaderMap::new(),