From 7517aac9e989dd9a9795f809a5d489b224f50868 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Sun, 25 Jan 2015 11:10:49 -0500 Subject: [PATCH] Completely abstract sending responses over channels vs. listeners. --- components/net/file_loader.rs | 7 +++--- components/net/resource_task.rs | 39 ++++++++++++++++++++++++------ components/net_traits/lib.rs | 20 +++++++++++++-- tests/unit/net/image_cache_task.rs | 16 ++++++------ 4 files changed, 61 insertions(+), 21 deletions(-) diff --git a/components/net/file_loader.rs b/components/net/file_loader.rs index 26fda4074c1..2d02d9b4c19 100644 --- a/components/net/file_loader.rs +++ b/components/net/file_loader.rs @@ -2,17 +2,16 @@ * 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/. */ -use net_traits::{LoadData, Metadata, ProgressMsg, ResponseSenders}; +use net_traits::{LoadData, Metadata, ResponseSenders}; use net_traits::ProgressMsg::{Payload, Done}; use mime_classifier::MIMEClassifier; -use resource_task::{start_sending, start_sending_sniffed}; +use resource_task::{start_sending, start_sending_sniffed, ProgressSender}; use std::borrow::ToOwned; use std::fs::File; use std::io::Read; use std::path::PathBuf; use std::sync::Arc; -use std::sync::mpsc::Sender; use util::task::spawn_named; static READ_SIZE: usize = 8192; @@ -34,7 +33,7 @@ fn read_block(reader: &mut File) -> Result { } } -fn read_all(reader: &mut File, progress_chan: &Sender) +fn read_all(reader: &mut File, progress_chan: &ProgressSender) -> Result<(), String> { loop { match try!(read_block(reader)) { diff --git a/components/net/resource_task.rs b/components/net/resource_task.rs index 6f0d6994113..0d4bc19a64d 100644 --- a/components/net/resource_task.rs +++ b/components/net/resource_task.rs @@ -13,7 +13,7 @@ use cookie; use mime_classifier::MIMEClassifier; use net_traits::{ControlMsg, LoadData, LoadResponse, ResponseSenders, LoadConsumer}; -use net_traits::{Metadata, ProgressMsg, ResourceTask}; +use net_traits::{Metadata, ProgressMsg, ResourceTask, AsyncResponseTarget, ResponseAction}; use net_traits::ProgressMsg::Done; use util::opts; use util::task::spawn_named; @@ -58,22 +58,44 @@ pub fn global_init() { } } +pub enum ProgressSender { + Channel(Sender), + Listener(Box), +} + +impl ProgressSender { + //XXXjdm return actual error + pub fn send(&self, msg: ProgressMsg) -> Result<(), ()> { + match *self { + ProgressSender::Channel(ref c) => c.send(msg).map_err(|_| ()), + ProgressSender::Listener(ref b) => { + let action = match msg { + ProgressMsg::Payload(buf) => ResponseAction::DataAvailable(buf), + ProgressMsg::Done(status) => ResponseAction::ResponseComplete(status), + }; + b.invoke_with_listener(action); + Ok(()) + } + } + } +} + /// For use by loaders in responding to a Load message. -pub fn start_sending(start_chan: ResponseSenders, metadata: Metadata) -> Sender { +pub fn start_sending(start_chan: ResponseSenders, metadata: Metadata) -> ProgressSender { start_sending_opt(start_chan, metadata).ok().unwrap() } /// For use by loaders in responding to a Load message that allows content sniffing. pub fn start_sending_sniffed(start_chan: ResponseSenders, metadata: Metadata, classifier: Arc, partial_body: &Vec) - -> Sender { + -> ProgressSender { start_sending_sniffed_opt(start_chan, metadata, classifier, partial_body).ok().unwrap() } /// For use by loaders in responding to a Load message that allows content sniffing. pub fn start_sending_sniffed_opt(start_chan: ResponseSenders, mut metadata: Metadata, classifier: Arc, partial_body: &Vec) - -> Result, ()> { + -> Result { if opts::get().sniff_mime_types { // TODO: should be calculated in the resource loader, from pull requeset #4094 let nosniff = false; @@ -94,7 +116,7 @@ pub fn start_sending_sniffed_opt(start_chan: ResponseSenders, mut metadata: Meta } /// For use by loaders in responding to a Load message. -pub fn start_sending_opt(start_chan: ResponseSenders, metadata: Metadata) -> Result, ()> { +pub fn start_sending_opt(start_chan: ResponseSenders, metadata: Metadata) -> Result { match start_chan { ResponseSenders::Channel(start_chan) => { let (progress_chan, progress_port) = channel(); @@ -103,11 +125,14 @@ pub fn start_sending_opt(start_chan: ResponseSenders, metadata: Metadata) -> Res progress_port: progress_port, }); match result { - Ok(_) => Ok(progress_chan), + Ok(_) => Ok(ProgressSender::Channel(progress_chan)), Err(_) => Err(()) } } - ResponseSenders::Listener(_) => panic!(), + ResponseSenders::Listener(target) => { + target.invoke_with_listener(ResponseAction::HeadersAvailable(metadata)); + Ok(ProgressSender::Listener(target)) + } } } diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index 5914922c275..660e3d05320 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -72,8 +72,24 @@ pub trait AsyncResponseListener { fn response_complete(&self, status: Result<(), String>); } +pub enum ResponseAction { + HeadersAvailable(Metadata), + DataAvailable(Vec), + ResponseComplete(Result<(), String>) +} + +impl ResponseAction { + pub fn process(self, listener: &AsyncResponseListener) { + match self { + ResponseAction::HeadersAvailable(m) => listener.headers_available(m), + ResponseAction::DataAvailable(d) => listener.data_available(d), + ResponseAction::ResponseComplete(r) => listener.response_complete(r), + } + } +} + pub trait AsyncResponseTarget { - fn get_listener(&self) -> &AsyncResponseListener; + fn invoke_with_listener(&self, action: ResponseAction); } pub enum LoadConsumer { @@ -174,7 +190,7 @@ pub enum CookieSource { pub enum ResponseSenders { Channel(Sender), - Listener(Box), + Listener(Box), } impl ResponseSenders { diff --git a/tests/unit/net/image_cache_task.rs b/tests/unit/net/image_cache_task.rs index 5b6cac13c09..a12e9b2b2e0 100644 --- a/tests/unit/net/image_cache_task.rs +++ b/tests/unit/net/image_cache_task.rs @@ -6,7 +6,7 @@ use net::image_cache_task::*; use net_traits::image_cache_task::ImageResponseMsg::*; use net_traits::image_cache_task::Msg::*; -use net::resource_task::start_sending; +use net::resource_task::{start_sending, ProgressSender}; use net_traits::{ControlMsg, Metadata, ProgressMsg, ResourceTask, ResponseSenders}; use net_traits::image_cache_task::{ImageCacheTask, ImageCacheTaskClient, ImageResponseMsg, Msg}; use net_traits::ProgressMsg::{Payload, Done}; @@ -41,7 +41,7 @@ impl ImageCacheTaskHelper for ImageCacheTask { } trait Closure { - fn invoke(&self, _response: Sender) { } + fn invoke(&self, _response: ProgressSender) { } } struct DoesNothing; impl Closure for DoesNothing { } @@ -50,7 +50,7 @@ struct JustSendOK { url_requested_chan: Sender<()>, } impl Closure for JustSendOK { - fn invoke(&self, response: Sender) { + fn invoke(&self, response: ProgressSender) { self.url_requested_chan.send(()).unwrap(); response.send(Done(Ok(()))).unwrap(); } @@ -58,7 +58,7 @@ impl Closure for JustSendOK { struct SendTestImage; impl Closure for SendTestImage { - fn invoke(&self, response: Sender) { + fn invoke(&self, response: ProgressSender) { response.send(Payload(test_image_bin())).unwrap(); response.send(Done(Ok(()))).unwrap(); } @@ -66,7 +66,7 @@ impl Closure for SendTestImage { struct SendBogusImage; impl Closure for SendBogusImage { - fn invoke(&self, response: Sender) { + fn invoke(&self, response: ProgressSender) { response.send(Payload(vec!())).unwrap(); response.send(Done(Ok(()))).unwrap(); } @@ -74,7 +74,7 @@ impl Closure for SendBogusImage { struct SendTestImageErr; impl Closure for SendTestImageErr { - fn invoke(&self, response: Sender) { + fn invoke(&self, response: ProgressSender) { response.send(Payload(test_image_bin())).unwrap(); response.send(Done(Err("".to_string()))).unwrap(); } @@ -84,7 +84,7 @@ struct WaitSendTestImage { wait_port: Receiver<()>, } impl Closure for WaitSendTestImage { - fn invoke(&self, response: Sender) { + fn invoke(&self, response: ProgressSender) { // Don't send the data until after the client requests // the image self.wait_port.recv().unwrap(); @@ -97,7 +97,7 @@ struct WaitSendTestImageErr { wait_port: Receiver<()>, } impl Closure for WaitSendTestImageErr { - fn invoke(&self, response: Sender) { + fn invoke(&self, response: ProgressSender) { // Don't send the data until after the client requests // the image self.wait_port.recv().unwrap();