aboutsummaryrefslogtreecommitdiffstats
path: root/components/net_traits/image_cache_task.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/net_traits/image_cache_task.rs')
-rw-r--r--components/net_traits/image_cache_task.rs106
1 files changed, 106 insertions, 0 deletions
diff --git a/components/net_traits/image_cache_task.rs b/components/net_traits/image_cache_task.rs
new file mode 100644
index 00000000000..2ce4d78dbf4
--- /dev/null
+++ b/components/net_traits/image_cache_task.rs
@@ -0,0 +1,106 @@
+/* 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 http://mozilla.org/MPL/2.0/. */
+
+use image::base::Image;
+use {ControlMsg, LoadData, ProgressMsg, ResourceTask};
+use url::Url;
+
+use std::sync::Arc;
+use std::sync::mpsc::{channel, Sender};
+
+pub enum Msg {
+ /// Tell the cache that we may need a particular image soon. Must be posted
+ /// before Decode
+ Prefetch(Url),
+
+ /// Tell the cache to decode an image. Must be posted before GetImage/WaitForImage
+ Decode(Url),
+
+ /// Request an Image object for a URL. If the image is not is not immediately
+ /// available then ImageNotReady is returned.
+ GetImage(Url, Sender<ImageResponseMsg>),
+
+ /// Wait for an image to become available (or fail to load).
+ WaitForImage(Url, Sender<ImageResponseMsg>),
+
+ /// Clients must wait for a response before shutting down the ResourceTask
+ Exit(Sender<()>),
+
+ /// Used by the prefetch tasks to post back image binaries
+ StorePrefetchedImageData(Url, Result<Vec<u8>, ()>),
+
+ /// Used by the decoder tasks to post decoded images back to the cache
+ StoreImage(Url, Option<Arc<Box<Image>>>),
+
+ /// For testing
+ WaitForStore(Sender<()>),
+
+ /// For testing
+ WaitForStorePrefetched(Sender<()>),
+}
+
+#[derive(Clone)]
+pub enum ImageResponseMsg {
+ ImageReady(Arc<Box<Image>>),
+ ImageNotReady,
+ ImageFailed
+}
+
+impl PartialEq for ImageResponseMsg {
+ fn eq(&self, other: &ImageResponseMsg) -> bool {
+ match (self, other) {
+ (&ImageResponseMsg::ImageReady(..), &ImageResponseMsg::ImageReady(..)) => panic!("unimplemented comparison"),
+ (&ImageResponseMsg::ImageNotReady, &ImageResponseMsg::ImageNotReady) => true,
+ (&ImageResponseMsg::ImageFailed, &ImageResponseMsg::ImageFailed) => true,
+
+ (&ImageResponseMsg::ImageReady(..), _) | (&ImageResponseMsg::ImageNotReady, _) | (&ImageResponseMsg::ImageFailed, _) => false
+ }
+ }
+}
+
+#[derive(Clone)]
+pub struct ImageCacheTask {
+ pub chan: Sender<Msg>,
+}
+
+impl ImageCacheTask {
+ pub fn send(&self, msg: Msg) {
+ self.chan.send(msg).unwrap();
+ }
+}
+
+pub fn load_image_data(url: Url, resource_task: ResourceTask, placeholder: &[u8]) -> Result<Vec<u8>, ()> {
+ let (response_chan, response_port) = channel();
+ resource_task.send(ControlMsg::Load(LoadData::new(url.clone(), response_chan))).unwrap();
+
+ let mut image_data = vec!();
+
+ let progress_port = response_port.recv().unwrap().progress_port;
+ loop {
+ match progress_port.recv().unwrap() {
+ ProgressMsg::Payload(data) => {
+ image_data.push_all(&data);
+ }
+ ProgressMsg::Done(Ok(..)) => {
+ return Ok(image_data);
+ }
+ ProgressMsg::Done(Err(..)) => {
+ // Failure to load the requested image will return the
+ // placeholder instead. In case it failed to load at init(),
+ // we still recover and return Err() but nothing will be drawn.
+ if placeholder.len() != 0 {
+ debug!("image_cache_task: failed to load {:?}, use placeholder instead.", url);
+ // Clean in case there was an error after started loading the image.
+ image_data.clear();
+ image_data.push_all(&placeholder);
+ return Ok(image_data);
+ } else {
+ debug!("image_cache_task: invalid placeholder.");
+ return Err(());
+ }
+ }
+ }
+ }
+}
+