aboutsummaryrefslogtreecommitdiffstats
path: root/components/net/image_cache.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/net/image_cache.rs')
-rw-r--r--components/net/image_cache.rs128
1 files changed, 91 insertions, 37 deletions
diff --git a/components/net/image_cache.rs b/components/net/image_cache.rs
index b5f0c98d49d..fea75ee7b95 100644
--- a/components/net/image_cache.rs
+++ b/components/net/image_cache.rs
@@ -4,9 +4,13 @@
use embedder_traits::resources::{self, Resource};
use immeta::load_from_buf;
+use ipc_channel::ipc::IpcSender;
use net_traits::image::base::{load_from_memory, Image, ImageMetadata};
-use net_traits::image_cache::{CanRequestImages, CorsStatus, ImageCache, ImageResponder};
-use net_traits::image_cache::{ImageOrMetadataAvailable, ImageResponse, ImageState};
+use net_traits::image_cache::{
+ CanRequestImages, CorsStatus, ImageCache, ImageCacheResult, ImageResponder,
+ PendingImageResponse,
+};
+use net_traits::image_cache::{ImageOrMetadataAvailable, ImageResponse};
use net_traits::image_cache::{PendingImageId, UsePlaceholder};
use net_traits::request::CorsSettings;
use net_traits::{
@@ -16,7 +20,6 @@ use pixels::PixelFormat;
use servo_url::{ImmutableOrigin, ServoUrl};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap;
-use std::io;
use std::mem;
use std::sync::{Arc, Mutex};
use std::thread;
@@ -45,13 +48,10 @@ fn decode_bytes_sync(key: LoadKey, bytes: &[u8], cors: CorsStatus) -> DecoderMsg
}
}
-fn get_placeholder_image(
- webrender_api: &WebrenderIpcSender,
- data: &[u8],
-) -> io::Result<Arc<Image>> {
+fn get_placeholder_image(webrender_api: &WebrenderIpcSender, data: &[u8]) -> Arc<Image> {
let mut image = load_from_memory(&data, CorsStatus::Unsafe).unwrap();
set_webrender_image_key(webrender_api, &mut image);
- Ok(Arc::new(image))
+ Arc::new(image)
}
fn set_webrender_image_key(webrender_api: &WebrenderIpcSender, image: &mut Image) {
@@ -335,7 +335,7 @@ struct ImageCacheStore {
completed_loads: HashMap<ImageKey, CompletedLoad>,
// The placeholder image used when an image fails to load
- placeholder_image: Option<Arc<Image>>,
+ placeholder_image: Arc<Image>,
// The URL used for the placeholder image
placeholder_url: ServoUrl,
@@ -391,7 +391,7 @@ impl ImageCacheStore {
origin: ImmutableOrigin,
cors_setting: Option<CorsSettings>,
placeholder: UsePlaceholder,
- ) -> Option<Result<ImageOrMetadataAvailable, ImageState>> {
+ ) -> Option<Result<(Arc<Image>, ServoUrl), ()>> {
self.completed_loads
.get(&(url, origin, cors_setting))
.map(
@@ -400,13 +400,10 @@ impl ImageCacheStore {
(
&ImageResponse::PlaceholderLoaded(ref image, ref url),
UsePlaceholder::Yes,
- ) => Ok(ImageOrMetadataAvailable::ImageAvailable(
- image.clone(),
- url.clone(),
- )),
+ ) => Ok((image.clone(), url.clone())),
(&ImageResponse::PlaceholderLoaded(_, _), UsePlaceholder::No) |
(&ImageResponse::None, _) |
- (&ImageResponse::MetadataLoaded(_), _) => Err(ImageState::LoadError),
+ (&ImageResponse::MetadataLoaded(_), _) => Err(()),
},
)
}
@@ -436,25 +433,36 @@ impl ImageCache for ImageCacheImpl {
store: Arc::new(Mutex::new(ImageCacheStore {
pending_loads: AllPendingLoads::new(),
completed_loads: HashMap::new(),
- placeholder_image: get_placeholder_image(&webrender_api, &rippy_data).ok(),
+ placeholder_image: get_placeholder_image(&webrender_api, &rippy_data),
placeholder_url: ServoUrl::parse("chrome://resources/rippy.png").unwrap(),
webrender_api: webrender_api,
})),
}
}
- /// Return any available metadata or image for the given URL,
- /// or an indication that the image is not yet available if it is in progress,
- /// or else reserve a slot in the cache for the URL if the consumer can request images.
- fn find_image_or_metadata(
+ fn get_image(
+ &self,
+ url: ServoUrl,
+ origin: ImmutableOrigin,
+ cors_setting: Option<CorsSettings>,
+ ) -> Option<Arc<Image>> {
+ let store = self.store.lock().unwrap();
+ let result =
+ store.get_completed_image_if_available(url, origin, cors_setting, UsePlaceholder::No);
+ match result {
+ Some(Ok((img, _))) => Some(img),
+ _ => None,
+ }
+ }
+
+ fn get_cached_image_status(
&self,
url: ServoUrl,
origin: ImmutableOrigin,
cors_setting: Option<CorsSettings>,
use_placeholder: UsePlaceholder,
can_request: CanRequestImages,
- ) -> Result<ImageOrMetadataAvailable, ImageState> {
- debug!("Find image or metadata for {} ({:?})", url, origin);
+ ) -> ImageCacheResult {
let mut store = self.store.lock().unwrap();
if let Some(result) = store.get_completed_image_if_available(
url.clone(),
@@ -462,8 +470,18 @@ impl ImageCache for ImageCacheImpl {
cors_setting,
use_placeholder,
) {
- debug!("{} is available", url);
- return result;
+ match result {
+ Ok((image, image_url)) => {
+ debug!("{} is available", url);
+ return ImageCacheResult::Available(ImageOrMetadataAvailable::ImageAvailable(
+ image, image_url,
+ ));
+ },
+ Err(()) => {
+ debug!("{} is not available", url);
+ return ImageCacheResult::LoadError;
+ },
+ }
}
let decoded = {
@@ -481,20 +499,22 @@ impl ImageCache for ImageCacheImpl {
},
(&None, &Some(ref meta)) => {
debug!("Metadata available for {} ({:?})", url, key);
- return Ok(ImageOrMetadataAvailable::MetadataAvailable(meta.clone()));
+ return ImageCacheResult::Available(
+ ImageOrMetadataAvailable::MetadataAvailable(meta.clone()),
+ );
},
(&Some(Err(_)), _) | (&None, &None) => {
debug!("{} ({:?}) is still pending", url, key);
- return Err(ImageState::Pending(key));
+ return ImageCacheResult::Pending(key);
},
},
CacheResult::Miss(Some((key, _pl))) => {
debug!("Should be requesting {} ({:?})", url, key);
- return Err(ImageState::NotRequested(key));
+ return ImageCacheResult::ReadyForRequest(key);
},
CacheResult::Miss(None) => {
debug!("Couldn't find an entry for {}", url);
- return Err(ImageState::LoadError);
+ return ImageCacheResult::LoadError;
},
}
};
@@ -505,9 +525,48 @@ impl ImageCache for ImageCacheImpl {
// TODO: make this behaviour configurable according to the caller's needs.
store.handle_decoder(decoded);
match store.get_completed_image_if_available(url, origin, cors_setting, use_placeholder) {
- Some(result) => result,
- None => Err(ImageState::LoadError),
+ Some(Ok((image, image_url))) => ImageCacheResult::Available(
+ ImageOrMetadataAvailable::ImageAvailable(image, image_url),
+ ),
+ _ => ImageCacheResult::LoadError,
+ }
+ }
+
+ fn track_image(
+ &self,
+ url: ServoUrl,
+ origin: ImmutableOrigin,
+ cors_setting: Option<CorsSettings>,
+ sender: IpcSender<PendingImageResponse>,
+ use_placeholder: UsePlaceholder,
+ can_request: CanRequestImages,
+ ) -> ImageCacheResult {
+ debug!("Track image for {} ({:?})", url, origin);
+ let cache_result = self.get_cached_image_status(
+ url.clone(),
+ origin.clone(),
+ cors_setting,
+ use_placeholder,
+ can_request,
+ );
+
+ match cache_result {
+ ImageCacheResult::Available(ImageOrMetadataAvailable::MetadataAvailable(_)) => {
+ let store = self.store.lock().unwrap();
+ let id = store
+ .pending_loads
+ .url_to_load_key
+ .get(&(url, origin, cors_setting))
+ .unwrap();
+ self.add_listener(*id, ImageResponder::new(sender, *id));
+ },
+ ImageCacheResult::Pending(id) | ImageCacheResult::ReadyForRequest(id) => {
+ self.add_listener(id, ImageResponder::new(sender, id));
+ },
+ _ => {},
}
+
+ cache_result
}
/// Add a new listener for the given pending image id. If the image is already present,
@@ -600,13 +659,8 @@ impl ImageCache for ImageCacheImpl {
Err(_) => {
debug!("Processing error for {:?}", key);
let mut store = self.store.lock().unwrap();
- match store.placeholder_image.clone() {
- Some(placeholder_image) => store.complete_load(
- id,
- LoadResult::PlaceholderLoaded(placeholder_image),
- ),
- None => store.complete_load(id, LoadResult::None),
- }
+ let placeholder_image = store.placeholder_image.clone();
+ store.complete_load(id, LoadResult::PlaceholderLoaded(placeholder_image))
},
}
},