diff options
author | Josh Matthews <josh@joshmatthews.net> | 2019-10-03 17:36:02 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2019-10-04 15:08:40 -0400 |
commit | 1df8d57dc6adcf56c22b45053b3d2eca904d17d3 (patch) | |
tree | ce2ba8d6672925a95d551a0ece8ee9e279332e3e /components/net/image_cache.rs | |
parent | 583536c9406e685405d5b28da99dd8cab94c7d66 (diff) | |
download | servo-1df8d57dc6adcf56c22b45053b3d2eca904d17d3.tar.gz servo-1df8d57dc6adcf56c22b45053b3d2eca904d17d3.zip |
Support CORS attributes for image elements.
Diffstat (limited to 'components/net/image_cache.rs')
-rw-r--r-- | components/net/image_cache.rs | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/components/net/image_cache.rs b/components/net/image_cache.rs index 89397483ee3..1504f1c06e5 100644 --- a/components/net/image_cache.rs +++ b/components/net/image_cache.rs @@ -8,6 +8,7 @@ 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::{PendingImageId, UsePlaceholder}; +use net_traits::request::CorsSettings; use net_traits::{FetchMetadata, FetchResponseMsg, FilteredMetadata, NetworkError}; use pixels::PixelFormat; use servo_url::{ImmutableOrigin, ServoUrl}; @@ -92,6 +93,9 @@ fn set_webrender_image_key(webrender_api: &webrender_api::RenderApi, image: &mut // Aux structs and enums. // ====================================================================== +/// https://html.spec.whatwg.org/multipage/#list-of-available-images +type ImageKey = (ServoUrl, ImmutableOrigin, Option<CorsSettings>); + // Represents all the currently pending loads/decodings. For // performance reasons, loads are indexed by a dedicated load key. struct AllPendingLoads { @@ -101,7 +105,7 @@ struct AllPendingLoads { // Get a load key from its url and requesting origin. Used ony when starting and // finishing a load or when adding a new listener. - url_to_load_key: HashMap<(ServoUrl, ImmutableOrigin), LoadKey>, + url_to_load_key: HashMap<ImageKey, LoadKey>, // A counter used to generate instances of LoadKey keygen: LoadKeyGenerator, @@ -124,7 +128,11 @@ impl AllPendingLoads { fn remove(&mut self, key: &LoadKey) -> Option<PendingLoad> { self.loads.remove(key).and_then(|pending_load| { self.url_to_load_key - .remove(&(pending_load.url.clone(), pending_load.load_origin.clone())) + .remove(&( + pending_load.url.clone(), + pending_load.load_origin.clone(), + pending_load.cors_setting, + )) .unwrap(); Some(pending_load) }) @@ -134,9 +142,13 @@ impl AllPendingLoads { &'a mut self, url: ServoUrl, origin: ImmutableOrigin, + cors_status: Option<CorsSettings>, can_request: CanRequestImages, ) -> CacheResult<'a> { - match self.url_to_load_key.entry((url.clone(), origin.clone())) { + match self + .url_to_load_key + .entry((url.clone(), origin.clone(), cors_status)) + { Occupied(url_entry) => { let load_key = url_entry.get(); CacheResult::Hit(*load_key, self.loads.get_mut(load_key).unwrap()) @@ -149,7 +161,7 @@ impl AllPendingLoads { let load_key = self.keygen.next(); url_entry.insert(load_key); - let pending_load = PendingLoad::new(url, origin); + let pending_load = PendingLoad::new(url, origin, cors_status); match self.loads.entry(load_key) { Occupied(_) => unreachable!(), Vacant(load_entry) => { @@ -274,6 +286,9 @@ struct PendingLoad { /// The origin that requested this load. load_origin: ImmutableOrigin, + /// The CORS attribute setting for the requesting + cors_setting: Option<CorsSettings>, + /// The CORS status of this image response. cors_status: CorsStatus, @@ -282,7 +297,11 @@ struct PendingLoad { } impl PendingLoad { - fn new(url: ServoUrl, load_origin: ImmutableOrigin) -> PendingLoad { + fn new( + url: ServoUrl, + load_origin: ImmutableOrigin, + cors_setting: Option<CorsSettings>, + ) -> PendingLoad { PendingLoad { bytes: ImageBytes::InProgress(vec![]), metadata: None, @@ -291,6 +310,7 @@ impl PendingLoad { url: url, load_origin, final_url: None, + cors_setting, cors_status: CorsStatus::Unsafe, } } @@ -308,7 +328,7 @@ struct ImageCacheStore { pending_loads: AllPendingLoads, // Images that have finished loading (successful or not) - completed_loads: HashMap<(ServoUrl, ImmutableOrigin), CompletedLoad>, + completed_loads: HashMap<ImageKey, CompletedLoad>, // The placeholder image used when an image fails to load placeholder_image: Option<Arc<Image>>, @@ -346,7 +366,11 @@ impl ImageCacheStore { let completed_load = CompletedLoad::new(image_response.clone(), key); self.completed_loads.insert( - (pending_load.url.into(), pending_load.load_origin), + ( + pending_load.url.into(), + pending_load.load_origin, + pending_load.cors_setting, + ), completed_load, ); @@ -361,10 +385,11 @@ impl ImageCacheStore { &self, url: ServoUrl, origin: ImmutableOrigin, + cors_setting: Option<CorsSettings>, placeholder: UsePlaceholder, ) -> Option<Result<ImageOrMetadataAvailable, ImageState>> { self.completed_loads - .get(&(url, origin)) + .get(&(url, origin, cors_setting)) .map( |completed_load| match (&completed_load.image_response, placeholder) { (&ImageResponse::Loaded(ref image, ref url), _) | @@ -421,22 +446,29 @@ impl ImageCache for ImageCacheImpl { &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); let mut store = self.store.lock().unwrap(); - if let Some(result) = - store.get_completed_image_if_available(url.clone(), origin.clone(), use_placeholder) - { + if let Some(result) = store.get_completed_image_if_available( + url.clone(), + origin.clone(), + cors_setting, + use_placeholder, + ) { debug!("{} is available", url); return result; } let decoded = { - let result = store - .pending_loads - .get_cached(url.clone(), origin.clone(), can_request); + let result = store.pending_loads.get_cached( + url.clone(), + origin.clone(), + cors_setting, + can_request, + ); match result { CacheResult::Hit(key, pl) => match (&pl.result, &pl.metadata) { (&Some(Ok(_)), _) => { @@ -468,7 +500,7 @@ impl ImageCache for ImageCacheImpl { // and ignore the async decode when it finishes later. // TODO: make this behaviour configurable according to the caller's needs. store.handle_decoder(decoded); - match store.get_completed_image_if_available(url, origin, use_placeholder) { + match store.get_completed_image_if_available(url, origin, cors_setting, use_placeholder) { Some(result) => result, None => Err(ImageState::LoadError), } |