mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Implement WebResourceRequested Event. (#34961)
* Implement WebResourceRequested Event on the Embedder Layer Signed-off-by: zhuhaichao518 <zhuhaichao518@gmail.com> * fix and add test Signed-off-by: zhuhaichao518 <zhuhaichao518@gmail.com> * resolve comments Signed-off-by: zhuhaichao518 <zhuhaichao518@gmail.com> * remove sample code in webview Signed-off-by: zhuhaichao518 <zhuhaichao518@gmail.com> * remove typo Signed-off-by: zhuhaichao518 <zhuhaichao518@gmail.com> * ./mach format Signed-off-by: zhuhaichao518 <zhuhaichao518@gmail.com> * fix test fail caused by interception message Signed-off-by: zhuhaichao518 <zhuhaichao518@gmail.com> * update impl for is_for_main_frame Signed-off-by: zhuhaichao518 <zhuhaichao518@gmail.com> --------- Signed-off-by: zhuhaichao518 <zhuhaichao518@gmail.com>
This commit is contained in:
parent
7256590599
commit
a1326a7cf6
13 changed files with 364 additions and 9 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -1746,12 +1746,16 @@ dependencies = [
|
|||
"base",
|
||||
"cfg-if",
|
||||
"crossbeam-channel",
|
||||
"http 1.2.0",
|
||||
"hyper_serde",
|
||||
"ipc-channel",
|
||||
"keyboard-types",
|
||||
"log",
|
||||
"malloc_size_of_derive",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"servo_malloc_size_of",
|
||||
"servo_url",
|
||||
"webrender_api",
|
||||
"webxr-api",
|
||||
|
|
|
@ -215,6 +215,7 @@ mod from_script {
|
|||
Self::WebViewClosed(..) => target_variant!("WebViewClosed"),
|
||||
Self::WebViewFocused(..) => target_variant!("WebViewFocused"),
|
||||
Self::WebViewBlurred => target_variant!("WebViewBlurred"),
|
||||
Self::WebResourceRequested(..) => target_variant!("WebResourceRequested"),
|
||||
Self::AllowUnload(..) => target_variant!("AllowUnload"),
|
||||
Self::Keyboard(..) => target_variant!("Keyboard"),
|
||||
Self::ClearClipboardContents => target_variant!("ClearClipboardContents"),
|
||||
|
|
|
@ -43,6 +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::subresource_integrity::is_response_integrity_valid;
|
||||
|
||||
pub type Target<'a> = &'a mut (dyn FetchTaskTarget + Send);
|
||||
|
@ -60,6 +61,7 @@ pub struct FetchContext {
|
|||
pub devtools_chan: Option<Arc<Mutex<Sender<DevtoolsControlMsg>>>>,
|
||||
pub filemanager: Arc<Mutex<FileManager>>,
|
||||
pub file_token: FileTokenCheck,
|
||||
pub request_intercepter: Arc<Mutex<RequestIntercepter>>,
|
||||
pub cancellation_listener: Arc<CancellationListener>,
|
||||
pub timing: ServoArc<Mutex<ResourceFetchTiming>>,
|
||||
pub protocols: Arc<ProtocolRegistry>,
|
||||
|
@ -193,6 +195,18 @@ pub fn should_request_be_blocked_by_csp(
|
|||
.unwrap_or(csp::CheckResult::Allowed)
|
||||
}
|
||||
|
||||
pub fn maybe_intercept_request(
|
||||
request: &mut Request,
|
||||
context: &FetchContext,
|
||||
response: &mut Option<Response>,
|
||||
) {
|
||||
context
|
||||
.request_intercepter
|
||||
.lock()
|
||||
.unwrap()
|
||||
.intercept_request(request, response, context);
|
||||
}
|
||||
|
||||
/// [Main fetch](https://fetch.spec.whatwg.org/#concept-main-fetch)
|
||||
pub async fn main_fetch(
|
||||
fetch_params: &mut FetchParams,
|
||||
|
@ -299,6 +313,9 @@ pub async fn main_fetch(
|
|||
let current_url = request.current_url();
|
||||
let current_scheme = current_url.scheme();
|
||||
|
||||
// Intercept the request and maybe override the response.
|
||||
maybe_intercept_request(request, context, &mut response);
|
||||
|
||||
let mut response = match response {
|
||||
Some(res) => res,
|
||||
None => {
|
||||
|
|
|
@ -18,6 +18,7 @@ pub mod image_cache;
|
|||
pub mod local_directory_listing;
|
||||
pub mod mime_classifier;
|
||||
pub mod protocols;
|
||||
pub mod request_intercepter;
|
||||
pub mod resource_thread;
|
||||
mod storage_thread;
|
||||
pub mod subresource_integrity;
|
||||
|
|
104
components/net/request_intercepter.rs
Normal file
104
components/net/request_intercepter.rs
Normal file
|
@ -0,0 +1,104 @@
|
|||
/* 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<Response>,
|
||||
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((
|
||||
request.target_browsing_context_id,
|
||||
EmbedderMsg::WebResourceRequested(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;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -54,6 +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::storage_thread::StorageThreadFactory;
|
||||
use crate::websocket_loader;
|
||||
|
||||
|
@ -552,6 +553,7 @@ pub struct CoreResourceManager {
|
|||
devtools_sender: Option<Sender<DevtoolsControlMsg>>,
|
||||
sw_managers: HashMap<ImmutableOrigin, IpcSender<CustomResponseMediator>>,
|
||||
filemanager: FileManager,
|
||||
request_intercepter: RequestIntercepter,
|
||||
thread_pool: Arc<CoreResourceThreadPool>,
|
||||
ca_certificates: CACertificates,
|
||||
ignore_certificate_errors: bool,
|
||||
|
@ -703,7 +705,8 @@ impl CoreResourceManager {
|
|||
user_agent,
|
||||
devtools_sender,
|
||||
sw_managers: Default::default(),
|
||||
filemanager: FileManager::new(embedder_proxy, Arc::downgrade(&pool_handle)),
|
||||
filemanager: FileManager::new(embedder_proxy.clone(), Arc::downgrade(&pool_handle)),
|
||||
request_intercepter: RequestIntercepter::new(embedder_proxy),
|
||||
thread_pool: pool_handle,
|
||||
ca_certificates,
|
||||
ignore_certificate_errors,
|
||||
|
@ -746,6 +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 timing_type = match request_builder.destination {
|
||||
Destination::Document => ResourceTimingType::Navigation,
|
||||
|
@ -787,6 +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)),
|
||||
cancellation_listener,
|
||||
timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new(request.timing_type()))),
|
||||
protocols,
|
||||
|
|
|
@ -30,6 +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::resource_thread::CoreResourceThreadPool;
|
||||
use net_traits::filemanager_thread::FileTokenCheck;
|
||||
use net_traits::http_status::HttpStatus;
|
||||
|
@ -47,8 +48,9 @@ use uuid::Uuid;
|
|||
|
||||
use crate::http_loader::{expect_devtools_http_request, expect_devtools_http_response};
|
||||
use crate::{
|
||||
create_embedder_proxy, create_http_state, fetch, fetch_with_context, fetch_with_cors_cache,
|
||||
make_body, make_server, make_ssl_server, new_fetch_context, DEFAULT_USER_AGENT,
|
||||
create_embedder_proxy, create_embedder_proxy_and_receiver, create_http_state, fetch,
|
||||
fetch_with_context, fetch_with_cors_cache, make_body, make_server, make_ssl_server,
|
||||
new_fetch_context, DEFAULT_USER_AGENT,
|
||||
};
|
||||
|
||||
// TODO write a struct that impls Handler for storing test values
|
||||
|
@ -695,15 +697,18 @@ fn test_fetch_with_hsts() {
|
|||
|
||||
let (server, url) = make_ssl_server(handler);
|
||||
|
||||
let embedder_proxy = create_embedder_proxy();
|
||||
|
||||
let mut context = FetchContext {
|
||||
state: Arc::new(create_http_state(None)),
|
||||
user_agent: DEFAULT_USER_AGENT.into(),
|
||||
devtools_chan: None,
|
||||
filemanager: Arc::new(Mutex::new(FileManager::new(
|
||||
create_embedder_proxy(),
|
||||
embedder_proxy.clone(),
|
||||
Weak::new(),
|
||||
))),
|
||||
file_token: FileTokenCheck::NotRequired,
|
||||
request_intercepter: Arc::new(Mutex::new(RequestIntercepter::new(embedder_proxy))),
|
||||
cancellation_listener: Arc::new(Default::default()),
|
||||
timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new(
|
||||
ResourceTimingType::Navigation,
|
||||
|
@ -752,15 +757,18 @@ fn test_load_adds_host_to_hsts_list_when_url_is_https() {
|
|||
let (server, mut url) = make_ssl_server(handler);
|
||||
url.as_mut_url().set_scheme("https").unwrap();
|
||||
|
||||
let embedder_proxy = create_embedder_proxy();
|
||||
|
||||
let mut context = FetchContext {
|
||||
state: Arc::new(create_http_state(None)),
|
||||
user_agent: DEFAULT_USER_AGENT.into(),
|
||||
devtools_chan: None,
|
||||
filemanager: Arc::new(Mutex::new(FileManager::new(
|
||||
create_embedder_proxy(),
|
||||
embedder_proxy.clone(),
|
||||
Weak::new(),
|
||||
))),
|
||||
file_token: FileTokenCheck::NotRequired,
|
||||
request_intercepter: Arc::new(Mutex::new(RequestIntercepter::new(embedder_proxy))),
|
||||
cancellation_listener: Arc::new(Default::default()),
|
||||
timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new(
|
||||
ResourceTimingType::Navigation,
|
||||
|
@ -811,15 +819,18 @@ fn test_fetch_self_signed() {
|
|||
let (server, mut url) = make_ssl_server(handler);
|
||||
url.as_mut_url().set_scheme("https").unwrap();
|
||||
|
||||
let embedder_proxy = create_embedder_proxy();
|
||||
|
||||
let mut context = FetchContext {
|
||||
state: Arc::new(create_http_state(None)),
|
||||
user_agent: DEFAULT_USER_AGENT.into(),
|
||||
devtools_chan: None,
|
||||
filemanager: Arc::new(Mutex::new(FileManager::new(
|
||||
create_embedder_proxy(),
|
||||
embedder_proxy.clone(),
|
||||
Weak::new(),
|
||||
))),
|
||||
file_token: FileTokenCheck::NotRequired,
|
||||
request_intercepter: Arc::new(Mutex::new(RequestIntercepter::new(embedder_proxy))),
|
||||
cancellation_listener: Arc::new(Default::default()),
|
||||
timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new(
|
||||
ResourceTimingType::Navigation,
|
||||
|
@ -1320,3 +1331,102 @@ fn test_fetch_with_devtools() {
|
|||
assert_eq!(devhttprequest, httprequest);
|
||||
assert_eq!(devhttpresponse, httpresponse);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fetch_request_intercepted() {
|
||||
static BODY_PART1: &[u8] = b"Request is";
|
||||
static BODY_PART2: &[u8] = b" intercepted";
|
||||
static EXPECTED_BODY: &[u8] = b"Request is intercepted";
|
||||
static HEADERNAME: &str = "custom-header";
|
||||
static HEADERVALUE: &str = "custom-value";
|
||||
static STATUS_MESSAGE: &[u8] = b"custom status message";
|
||||
|
||||
let (embedder_proxy, mut embedder_receiver) = create_embedder_proxy_and_receiver();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let (_browser_context_id, embedder_msg) = embedder_receiver.recv_embedder_msg();
|
||||
match embedder_msg {
|
||||
embedder_traits::EmbedderMsg::WebResourceRequested(
|
||||
web_resource_request,
|
||||
response_sender,
|
||||
) => {
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert(
|
||||
HeaderName::from_static(HEADERNAME),
|
||||
HeaderValue::from_static(HEADERVALUE),
|
||||
);
|
||||
let response =
|
||||
embedder_traits::WebResourceResponse::new(web_resource_request.url.clone())
|
||||
.headers(headers)
|
||||
.status_code(StatusCode::FOUND)
|
||||
.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 _ = response_sender.send(msg2);
|
||||
let msg3 = embedder_traits::WebResourceResponseMsg::Body(
|
||||
embedder_traits::HttpBodyData::Chunk(BODY_PART2.to_vec()),
|
||||
);
|
||||
let _ = response_sender.send(msg3);
|
||||
let _ = response_sender.send(embedder_traits::WebResourceResponseMsg::Body(
|
||||
embedder_traits::HttpBodyData::Done,
|
||||
));
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
});
|
||||
|
||||
let mut context = FetchContext {
|
||||
state: Arc::new(create_http_state(None)),
|
||||
user_agent: DEFAULT_USER_AGENT.into(),
|
||||
devtools_chan: None,
|
||||
filemanager: Arc::new(Mutex::new(FileManager::new(
|
||||
embedder_proxy.clone(),
|
||||
Weak::new(),
|
||||
))),
|
||||
file_token: FileTokenCheck::NotRequired,
|
||||
request_intercepter: Arc::new(Mutex::new(RequestIntercepter::new(embedder_proxy))),
|
||||
cancellation_listener: Arc::new(Default::default()),
|
||||
timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new(
|
||||
ResourceTimingType::Navigation,
|
||||
))),
|
||||
protocols: Arc::new(ProtocolRegistry::default()),
|
||||
};
|
||||
|
||||
let url = ServoUrl::parse("http://www.example.org").unwrap();
|
||||
let request = RequestBuilder::new(url.clone(), Referrer::NoReferrer)
|
||||
.origin(url.origin())
|
||||
.build();
|
||||
let response = fetch_with_context(request, &mut context);
|
||||
|
||||
assert!(
|
||||
response
|
||||
.headers
|
||||
.get(HEADERNAME)
|
||||
.map(|v| v == HEADERVALUE)
|
||||
.unwrap_or(false),
|
||||
"The custom header does not exist or has an incorrect value!"
|
||||
);
|
||||
|
||||
let body = response.body.lock().unwrap();
|
||||
match &*body {
|
||||
ResponseBody::Done(data) => {
|
||||
assert_eq!(data, &EXPECTED_BODY, "Body content does not match");
|
||||
},
|
||||
_ => panic!("Expected ResponseBody::Done, but got {:?}", *body),
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
response.status.code(),
|
||||
StatusCode::FOUND,
|
||||
"Status code does not match!"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
response.status.message(),
|
||||
STATUS_MESSAGE,
|
||||
"The status_message was not set correctly!"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -42,6 +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::resource_thread::CoreResourceThreadPool;
|
||||
use net::test::HttpState;
|
||||
use net_traits::filemanager_thread::FileTokenCheck;
|
||||
|
@ -128,7 +129,7 @@ fn receive_credential_prompt_msgs(
|
|||
username: Option<String>,
|
||||
password: Option<String>,
|
||||
) -> std::thread::JoinHandle<()> {
|
||||
std::thread::spawn(move || {
|
||||
std::thread::spawn(move || loop {
|
||||
let (_browser_context_id, embedder_msg) = embedder_receiver.recv_embedder_msg();
|
||||
match embedder_msg {
|
||||
embedder_traits::EmbedderMsg::Prompt(prompt_definition, _prompt_origin) => {
|
||||
|
@ -140,7 +141,9 @@ fn receive_credential_prompt_msgs(
|
|||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
break;
|
||||
},
|
||||
embedder_traits::EmbedderMsg::WebResourceRequested(_, _) => {},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
})
|
||||
|
@ -179,10 +182,11 @@ fn new_fetch_context(
|
|||
user_agent: DEFAULT_USER_AGENT.into(),
|
||||
devtools_chan: dc.map(|dc| Arc::new(Mutex::new(dc))),
|
||||
filemanager: Arc::new(Mutex::new(FileManager::new(
|
||||
sender,
|
||||
sender.clone(),
|
||||
pool_handle.unwrap_or_else(|| Weak::new()),
|
||||
))),
|
||||
file_token: FileTokenCheck::NotRequired,
|
||||
request_intercepter: Arc::new(Mutex::new(RequestIntercepter::new(sender))),
|
||||
cancellation_listener: Arc::new(Default::default()),
|
||||
timing: ServoArc::new(Mutex::new(ResourceFetchTiming::new(
|
||||
ResourceTimingType::Navigation,
|
||||
|
|
|
@ -18,10 +18,14 @@ webxr = ["dep:webxr-api"]
|
|||
base = { workspace = true }
|
||||
cfg-if = { workspace = true }
|
||||
crossbeam-channel = { workspace = true }
|
||||
http = { workspace = true }
|
||||
hyper_serde = { workspace = true }
|
||||
ipc-channel = { workspace = true }
|
||||
keyboard-types = { workspace = true }
|
||||
log = { workspace = true }
|
||||
num-derive = "0.4"
|
||||
malloc_size_of = { workspace = true }
|
||||
malloc_size_of_derive = { workspace = true }
|
||||
num-traits = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
servo_url = { path = "../../url" }
|
||||
|
|
|
@ -8,9 +8,11 @@ use std::fmt::{Debug, Error, Formatter};
|
|||
|
||||
use base::id::{PipelineId, TopLevelBrowsingContextId, WebViewId};
|
||||
use crossbeam_channel::{Receiver, Sender};
|
||||
use http::{HeaderMap, Method, StatusCode};
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use keyboard_types::KeyboardEvent;
|
||||
use log::warn;
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use num_derive::FromPrimitive;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use servo_url::ServoUrl;
|
||||
|
@ -212,6 +214,7 @@ pub enum EmbedderMsg {
|
|||
LoadStart,
|
||||
/// The load of a page has completed
|
||||
LoadComplete,
|
||||
WebResourceRequested(WebResourceRequest, IpcSender<WebResourceResponseMsg>),
|
||||
/// A pipeline panicked. First string is the reason, second one is the backtrace.
|
||||
Panic(String, Option<String>),
|
||||
/// Open dialog to select bluetooth device.
|
||||
|
@ -282,6 +285,7 @@ impl Debug for EmbedderMsg {
|
|||
EmbedderMsg::SetFullscreenState(..) => write!(f, "SetFullscreenState"),
|
||||
EmbedderMsg::LoadStart => write!(f, "LoadStart"),
|
||||
EmbedderMsg::LoadComplete => write!(f, "LoadComplete"),
|
||||
EmbedderMsg::WebResourceRequested(..) => write!(f, "WebResourceRequested"),
|
||||
EmbedderMsg::Panic(..) => write!(f, "Panic"),
|
||||
EmbedderMsg::GetSelectedBluetoothDevice(..) => write!(f, "GetSelectedBluetoothDevice"),
|
||||
EmbedderMsg::SelectFiles(..) => write!(f, "SelectFiles"),
|
||||
|
@ -437,3 +441,101 @@ pub struct DualRumbleEffectParams {
|
|||
pub enum GamepadHapticEffectType {
|
||||
DualRumble(DualRumbleEffectParams),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
|
||||
pub struct WebResourceRequest {
|
||||
#[serde(
|
||||
deserialize_with = "::hyper_serde::deserialize",
|
||||
serialize_with = "::hyper_serde::serialize"
|
||||
)]
|
||||
#[ignore_malloc_size_of = "Defined in hyper"]
|
||||
pub method: Method,
|
||||
#[serde(
|
||||
deserialize_with = "::hyper_serde::deserialize",
|
||||
serialize_with = "::hyper_serde::serialize"
|
||||
)]
|
||||
#[ignore_malloc_size_of = "Defined in hyper"]
|
||||
pub headers: HeaderMap,
|
||||
pub url: ServoUrl,
|
||||
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(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<u8>),
|
||||
Done,
|
||||
Cancelled,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
|
||||
pub struct WebResourceResponse {
|
||||
pub url: ServoUrl,
|
||||
#[serde(
|
||||
deserialize_with = "::hyper_serde::deserialize",
|
||||
serialize_with = "::hyper_serde::serialize"
|
||||
)]
|
||||
#[ignore_malloc_size_of = "Defined in hyper"]
|
||||
pub headers: HeaderMap,
|
||||
#[serde(
|
||||
deserialize_with = "::hyper_serde::deserialize",
|
||||
serialize_with = "::hyper_serde::serialize"
|
||||
)]
|
||||
#[ignore_malloc_size_of = "Defined in hyper"]
|
||||
pub status_code: StatusCode,
|
||||
pub status_message: Vec<u8>,
|
||||
}
|
||||
|
||||
impl WebResourceResponse {
|
||||
pub fn new(url: ServoUrl) -> WebResourceResponse {
|
||||
WebResourceResponse {
|
||||
url,
|
||||
headers: HeaderMap::new(),
|
||||
status_code: StatusCode::OK,
|
||||
status_message: b"OK".to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn headers(mut self, headers: HeaderMap) -> WebResourceResponse {
|
||||
self.headers = headers;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn status_code(mut self, status_code: StatusCode) -> WebResourceResponse {
|
||||
self.status_code = status_code;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn status_message(mut self, status_message: Vec<u8>) -> WebResourceResponse {
|
||||
self.status_message = status_message;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,6 +154,7 @@ mod from_servo {
|
|||
Self::WebViewClosed(..) => target!("WebViewClosed"),
|
||||
Self::WebViewFocused(..) => target!("WebViewFocused"),
|
||||
Self::WebViewBlurred => target!("WebViewBlurred"),
|
||||
Self::WebResourceRequested(..) => target!("WebResourceRequested"),
|
||||
Self::AllowUnload(..) => target!("AllowUnload"),
|
||||
Self::Keyboard(..) => target!("Keyboard"),
|
||||
Self::ClearClipboardContents => target!("ClearClipboardContents"),
|
||||
|
|
|
@ -936,6 +936,7 @@ where
|
|||
}
|
||||
}
|
||||
},
|
||||
EmbedderMsg::WebResourceRequested(_web_resource_request, _response_sender) => {},
|
||||
EmbedderMsg::Shutdown => {
|
||||
self.shutdown_requested = true;
|
||||
},
|
||||
|
|
|
@ -645,7 +645,8 @@ impl ServoGlue {
|
|||
EmbedderMsg::EventDelivered(..) |
|
||||
EmbedderMsg::PlayGamepadHapticEffect(..) |
|
||||
EmbedderMsg::StopGamepadHapticEffect(..) |
|
||||
EmbedderMsg::ClearClipboardContents => {},
|
||||
EmbedderMsg::ClearClipboardContents |
|
||||
EmbedderMsg::WebResourceRequested(..) => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue