aboutsummaryrefslogtreecommitdiffstats
path: root/components/shared/net/image_cache.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/shared/net/image_cache.rs')
-rw-r--r--components/shared/net/image_cache.rs156
1 files changed, 156 insertions, 0 deletions
diff --git a/components/shared/net/image_cache.rs b/components/shared/net/image_cache.rs
new file mode 100644
index 00000000000..81d34964db4
--- /dev/null
+++ b/components/shared/net/image_cache.rs
@@ -0,0 +1,156 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+use std::sync::Arc;
+
+use ipc_channel::ipc::IpcSender;
+use log::debug;
+use malloc_size_of_derive::MallocSizeOf;
+use serde::{Deserialize, Serialize};
+use servo_url::{ImmutableOrigin, ServoUrl};
+
+use crate::image::base::{Image, ImageMetadata};
+use crate::request::CorsSettings;
+use crate::{FetchResponseMsg, WebrenderIpcSender};
+
+// ======================================================================
+// Aux structs and enums.
+// ======================================================================
+
+/// Indicating either entire image or just metadata availability
+#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
+pub enum ImageOrMetadataAvailable {
+ ImageAvailable {
+ #[ignore_malloc_size_of = "Arc"]
+ image: Arc<Image>,
+ url: ServoUrl,
+ is_placeholder: bool,
+ },
+ MetadataAvailable(ImageMetadata),
+}
+
+/// This is optionally passed to the image cache when requesting
+/// and image, and returned to the specified event loop when the
+/// image load completes. It is typically used to trigger a reflow
+/// and/or repaint.
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct ImageResponder {
+ id: PendingImageId,
+ sender: IpcSender<PendingImageResponse>,
+}
+
+impl ImageResponder {
+ pub fn new(sender: IpcSender<PendingImageResponse>, id: PendingImageId) -> ImageResponder {
+ ImageResponder {
+ sender: sender,
+ id: id,
+ }
+ }
+
+ pub fn respond(&self, response: ImageResponse) {
+ debug!("Notifying listener");
+ // This send can fail if thread waiting for this notification has panicked.
+ // That's not a case that's worth warning about.
+ // TODO(#15501): are there cases in which we should perform cleanup?
+ let _ = self.sender.send(PendingImageResponse {
+ response: response,
+ id: self.id,
+ });
+ }
+}
+
+/// The returned image.
+#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
+pub enum ImageResponse {
+ /// The requested image was loaded.
+ Loaded(#[ignore_malloc_size_of = "Arc"] Arc<Image>, ServoUrl),
+ /// The request image metadata was loaded.
+ MetadataLoaded(ImageMetadata),
+ /// The requested image failed to load, so a placeholder was loaded instead.
+ PlaceholderLoaded(#[ignore_malloc_size_of = "Arc"] Arc<Image>, ServoUrl),
+ /// Neither the requested image nor the placeholder could be loaded.
+ None,
+}
+
+/// The unique id for an image that has previously been requested.
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
+pub struct PendingImageId(pub u64);
+
+#[derive(Debug, Deserialize, Serialize)]
+pub struct PendingImageResponse {
+ pub response: ImageResponse,
+ pub id: PendingImageId,
+}
+
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
+pub enum UsePlaceholder {
+ No,
+ Yes,
+}
+
+// ======================================================================
+// ImageCache public API.
+// ======================================================================
+
+pub enum ImageCacheResult {
+ Available(ImageOrMetadataAvailable),
+ LoadError,
+ Pending(PendingImageId),
+ ReadyForRequest(PendingImageId),
+}
+
+pub trait ImageCache: Sync + Send {
+ fn new(webrender_api: WebrenderIpcSender) -> Self
+ where
+ Self: Sized;
+
+ /// Definitively check whether there is a cached, fully loaded image available.
+ fn get_image(
+ &self,
+ url: ServoUrl,
+ origin: ImmutableOrigin,
+ cors_setting: Option<CorsSettings>,
+ ) -> Option<Arc<Image>>;
+
+ fn get_cached_image_status(
+ &self,
+ url: ServoUrl,
+ origin: ImmutableOrigin,
+ cors_setting: Option<CorsSettings>,
+ use_placeholder: UsePlaceholder,
+ ) -> ImageCacheResult;
+
+ /// Add a listener for the provided pending image id, eventually called by
+ /// ImageCacheStore::complete_load.
+ /// If only metadata is available, Available(ImageOrMetadataAvailable) will
+ /// be returned.
+ /// If Available(ImageOrMetadataAvailable::Image) or LoadError is the final value,
+ /// the provided listener will be dropped (consumed & not added to PendingLoad).
+ fn track_image(
+ &self,
+ url: ServoUrl,
+ origin: ImmutableOrigin,
+ cors_setting: Option<CorsSettings>,
+ sender: IpcSender<PendingImageResponse>,
+ use_placeholder: UsePlaceholder,
+ ) -> ImageCacheResult;
+
+ /// 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);
+
+ /// Inform the image cache about a response for a pending request.
+ fn notify_pending_response(&self, id: PendingImageId, action: FetchResponseMsg);
+}
+
+/// Whether this response passed any CORS checks, and is thus safe to read from
+/// in cross-origin environments.
+#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
+pub enum CorsStatus {
+ /// The response is either same-origin or cross-origin but passed CORS checks.
+ Safe,
+ /// The response is cross-origin and did not pass CORS checks. It is unsafe
+ /// to expose pixel data to the requesting environment.
+ Unsafe,
+}