mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Abstractify the Listener abstractions further
This commit is contained in:
parent
2cbc8dee25
commit
d4f428ad95
7 changed files with 47 additions and 17 deletions
|
@ -187,6 +187,13 @@ pub trait FetchTaskTarget {
|
||||||
fn process_response_eof(&mut self, response: &response::Response);
|
fn process_response_eof(&mut self, response: &response::Response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait FetchResponseListener {
|
||||||
|
fn process_request_body(&mut self);
|
||||||
|
fn process_request_eof(&mut self);
|
||||||
|
fn process_response(&mut self, metadata: Result<Metadata, NetworkError>);
|
||||||
|
fn process_response_eof(&mut self, response: Result<Vec<u8>, NetworkError>);
|
||||||
|
}
|
||||||
|
|
||||||
impl FetchTaskTarget for IpcSender<FetchResponseMsg> {
|
impl FetchTaskTarget for IpcSender<FetchResponseMsg> {
|
||||||
fn process_request_body(&mut self, _: &request::Request) {
|
fn process_request_body(&mut self, _: &request::Request) {
|
||||||
let _ = self.send(FetchResponseMsg::ProcessRequestBody);
|
let _ = self.send(FetchResponseMsg::ProcessRequestBody);
|
||||||
|
@ -217,6 +224,10 @@ impl FetchTaskTarget for IpcSender<FetchResponseMsg> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Action<Listener> {
|
||||||
|
fn process(self, listener: &mut Listener);
|
||||||
|
}
|
||||||
|
|
||||||
/// A listener for asynchronous network events. Cancelling the underlying request is unsupported.
|
/// A listener for asynchronous network events. Cancelling the underlying request is unsupported.
|
||||||
pub trait AsyncResponseListener {
|
pub trait AsyncResponseListener {
|
||||||
/// The response headers for a request have been received.
|
/// The response headers for a request have been received.
|
||||||
|
@ -241,9 +252,9 @@ pub enum ResponseAction {
|
||||||
ResponseComplete(Result<(), NetworkError>)
|
ResponseComplete(Result<(), NetworkError>)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResponseAction {
|
impl<T: AsyncResponseListener> Action<T> for ResponseAction {
|
||||||
/// Execute the default action on a provided listener.
|
/// Execute the default action on a provided listener.
|
||||||
pub fn process(self, listener: &mut AsyncResponseListener) {
|
fn process(self, listener: &mut T) {
|
||||||
match self {
|
match self {
|
||||||
ResponseAction::HeadersAvailable(m) => listener.headers_available(m),
|
ResponseAction::HeadersAvailable(m) => listener.headers_available(m),
|
||||||
ResponseAction::DataAvailable(d) => listener.data_available(d),
|
ResponseAction::DataAvailable(d) => listener.data_available(d),
|
||||||
|
@ -252,6 +263,18 @@ impl ResponseAction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: FetchResponseListener> Action<T> for FetchResponseMsg {
|
||||||
|
/// Execute the default action on a provided listener.
|
||||||
|
fn process(self, listener: &mut T) {
|
||||||
|
match self {
|
||||||
|
FetchResponseMsg::ProcessRequestBody => listener.process_request_body(),
|
||||||
|
FetchResponseMsg::ProcessRequestEOF => listener.process_request_eof(),
|
||||||
|
FetchResponseMsg::ProcessResponse(meta) => listener.process_response(meta),
|
||||||
|
FetchResponseMsg::ProcessResponseEOF(data) => listener.process_response_eof(data),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A target for async networking events. Commonly used to dispatch a runnable event to another
|
/// A target for async networking events. Commonly used to dispatch a runnable event to another
|
||||||
/// thread storing the wrapped closure for later execution.
|
/// thread storing the wrapped closure for later execution.
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
|
|
|
@ -227,7 +227,7 @@ impl HTMLLinkElement {
|
||||||
sender: action_sender,
|
sender: action_sender,
|
||||||
};
|
};
|
||||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||||
listener.notify(message.to().unwrap());
|
listener.notify_action(message.to().unwrap());
|
||||||
});
|
});
|
||||||
|
|
||||||
if self.parser_inserted.get() {
|
if self.parser_inserted.get() {
|
||||||
|
|
|
@ -484,7 +484,7 @@ impl HTMLMediaElement {
|
||||||
sender: action_sender,
|
sender: action_sender,
|
||||||
};
|
};
|
||||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||||
listener.notify(message.to().unwrap());
|
listener.notify_action(message.to().unwrap());
|
||||||
});
|
});
|
||||||
|
|
||||||
// FIXME: we're supposed to block the load event much earlier than now
|
// FIXME: we're supposed to block the load event much earlier than now
|
||||||
|
|
|
@ -314,7 +314,7 @@ impl HTMLScriptElement {
|
||||||
sender: action_sender,
|
sender: action_sender,
|
||||||
};
|
};
|
||||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||||
listener.notify(message.to().unwrap());
|
listener.notify_action(message.to().unwrap());
|
||||||
});
|
});
|
||||||
|
|
||||||
doc.load_async(LoadType::Script(url), response_target);
|
doc.load_async(LoadType::Script(url), response_target);
|
||||||
|
|
|
@ -302,7 +302,7 @@ impl XMLHttpRequest {
|
||||||
sender: action_sender,
|
sender: action_sender,
|
||||||
};
|
};
|
||||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||||
listener.notify(message.to().unwrap());
|
listener.notify_action(message.to().unwrap());
|
||||||
});
|
});
|
||||||
core_resource_thread.send(Load(load_data, LoadConsumer::Listener(response_target), None)).unwrap();
|
core_resource_thread.send(Load(load_data, LoadConsumer::Listener(response_target), None)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use net_traits::{AsyncResponseListener, ResponseAction};
|
use net_traits::{Action, AsyncResponseListener, ResponseAction};
|
||||||
use script_runtime::ScriptThreadEventCategory::NetworkEvent;
|
use script_runtime::ScriptThreadEventCategory::NetworkEvent;
|
||||||
use script_runtime::{CommonScriptMsg, ScriptChan};
|
use script_runtime::{CommonScriptMsg, ScriptChan};
|
||||||
use script_thread::Runnable;
|
use script_thread::Runnable;
|
||||||
|
@ -10,13 +10,13 @@ use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
/// An off-thread sink for async network event runnables. All such events are forwarded to
|
/// An off-thread sink for async network event runnables. All such events are forwarded to
|
||||||
/// a target thread, where they are invoked on the provided context object.
|
/// a target thread, where they are invoked on the provided context object.
|
||||||
pub struct NetworkListener<T: AsyncResponseListener + PreInvoke + Send + 'static> {
|
pub struct NetworkListener<Listener: PreInvoke + Send + 'static> {
|
||||||
pub context: Arc<Mutex<T>>,
|
pub context: Arc<Mutex<Listener>>,
|
||||||
pub script_chan: Box<ScriptChan + Send>,
|
pub script_chan: Box<ScriptChan + Send>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: AsyncResponseListener + PreInvoke + Send + 'static> NetworkListener<T> {
|
impl<Listener: PreInvoke + Send + 'static> NetworkListener<Listener> {
|
||||||
pub fn notify(&self, action: ResponseAction) {
|
pub fn notify<A: Action<Listener>+Send+'static>(&self, action: A) {
|
||||||
if let Err(err) = self.script_chan.send(CommonScriptMsg::RunnableMsg(NetworkEvent, box ListenerRunnable {
|
if let Err(err) = self.script_chan.send(CommonScriptMsg::RunnableMsg(NetworkEvent, box ListenerRunnable {
|
||||||
context: self.context.clone(),
|
context: self.context.clone(),
|
||||||
action: action,
|
action: action,
|
||||||
|
@ -26,6 +26,13 @@ impl<T: AsyncResponseListener + PreInvoke + Send + 'static> NetworkListener<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// helps type inference
|
||||||
|
impl<Listener: AsyncResponseListener + PreInvoke + Send + 'static> NetworkListener<Listener> {
|
||||||
|
pub fn notify_action(&self, action: ResponseAction) {
|
||||||
|
self.notify(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A gating mechanism that runs before invoking the runnable on the target thread.
|
/// A gating mechanism that runs before invoking the runnable on the target thread.
|
||||||
/// If the `should_invoke` method returns false, the runnable is discarded without
|
/// If the `should_invoke` method returns false, the runnable is discarded without
|
||||||
/// being invoked.
|
/// being invoked.
|
||||||
|
@ -36,13 +43,13 @@ pub trait PreInvoke {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A runnable for moving the async network events between threads.
|
/// A runnable for moving the async network events between threads.
|
||||||
struct ListenerRunnable<T: AsyncResponseListener + PreInvoke + Send> {
|
struct ListenerRunnable<A: Action<Listener>+Send+'static, Listener: PreInvoke + Send> {
|
||||||
context: Arc<Mutex<T>>,
|
context: Arc<Mutex<Listener>>,
|
||||||
action: ResponseAction,
|
action: A,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: AsyncResponseListener + PreInvoke + Send> Runnable for ListenerRunnable<T> {
|
impl<A: Action<Listener>+Send+'static, Listener: PreInvoke + Send> Runnable for ListenerRunnable<A, Listener> {
|
||||||
fn handler(self: Box<ListenerRunnable<T>>) {
|
fn handler(self: Box<ListenerRunnable<A, Listener>>) {
|
||||||
let this = *self;
|
let this = *self;
|
||||||
let mut context = this.context.lock().unwrap();
|
let mut context = this.context.lock().unwrap();
|
||||||
if context.should_invoke() {
|
if context.should_invoke() {
|
||||||
|
|
|
@ -1947,7 +1947,7 @@ impl ScriptThread {
|
||||||
script_chan: self.chan.clone(),
|
script_chan: self.chan.clone(),
|
||||||
};
|
};
|
||||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||||
listener.notify(message.to().unwrap());
|
listener.notify_action(message.to().unwrap());
|
||||||
});
|
});
|
||||||
let response_target = AsyncResponseTarget {
|
let response_target = AsyncResponseTarget {
|
||||||
sender: action_sender,
|
sender: action_sender,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue