mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Refactor ImageCache::find_image_or_metadata API.
This commit is contained in:
parent
7d1f968d52
commit
2742fd2bea
9 changed files with 266 additions and 227 deletions
|
@ -4,8 +4,12 @@
|
|||
|
||||
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::{
|
||||
CanRequestImages, CorsStatus, ImageCache, ImageCacheResult, ImageResponder,
|
||||
PendingImageResponse,
|
||||
};
|
||||
use net_traits::image_cache::{ImageOrMetadataAvailable, ImageResponse, ImageState};
|
||||
use net_traits::image_cache::{PendingImageId, UsePlaceholder};
|
||||
use net_traits::request::CorsSettings;
|
||||
|
@ -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,
|
||||
|
@ -436,34 +436,45 @@ 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(ImageOrMetadataAvailable::ImageAvailable(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(
|
||||
if let Some(Ok(result)) = store.get_completed_image_if_available(
|
||||
url.clone(),
|
||||
origin.clone(),
|
||||
cors_setting,
|
||||
use_placeholder,
|
||||
) {
|
||||
debug!("{} is available", url);
|
||||
return result;
|
||||
return ImageCacheResult::Available(result);
|
||||
}
|
||||
|
||||
let decoded = {
|
||||
|
@ -481,20 +492,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,11 +518,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(result)) => ImageCacheResult::Available(result),
|
||||
_ => 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,
|
||||
/// the responder will still receive the expected response.
|
||||
fn add_listener(&self, id: PendingImageId, listener: ImageResponder) {
|
||||
|
@ -600,13 +650,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))
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue