diff options
Diffstat (limited to 'components/net/image_cache.rs')
-rw-r--r-- | components/net/image_cache.rs | 128 |
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)) }, } }, |