summaryrefslogtreecommitdiffstats
path: root/layout/style/ImageLoader.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/style/ImageLoader.h')
-rw-r--r--layout/style/ImageLoader.h170
1 files changed, 170 insertions, 0 deletions
diff --git a/layout/style/ImageLoader.h b/layout/style/ImageLoader.h
new file mode 100644
index 0000000000..7b8b5338c4
--- /dev/null
+++ b/layout/style/ImageLoader.h
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 http://mozilla.org/MPL/2.0/. */
+
+// A class that handles style system image loads (other image loads are handled
+// by the nodes in the content tree).
+
+#ifndef mozilla_css_ImageLoader_h___
+#define mozilla_css_ImageLoader_h___
+
+#include "mozilla/CORSMode.h"
+#include "nsClassHashtable.h"
+#include "nsHashKeys.h"
+#include "nsRect.h"
+#include "nsTArray.h"
+#include "mozilla/Attributes.h"
+
+class nsIFrame;
+class imgIContainer;
+class imgIRequest;
+class imgRequestProxy;
+class nsPresContext;
+class nsIURI;
+class nsIPrincipal;
+class nsIRequest;
+
+namespace mozilla {
+struct MediaFeatureChange;
+struct StyleComputedUrl;
+namespace dom {
+class Document;
+}
+
+namespace css {
+
+/**
+ * NOTE: All methods must be called from the main thread unless otherwise
+ * specified.
+ */
+class ImageLoader final {
+ public:
+ static void Init();
+ static void Shutdown();
+
+ // We also associate flags alongside frames in the request-to-frames hashmap.
+ // These are used for special handling of events for requests.
+ enum class Flags : uint32_t {
+ // Used for bullets.
+ RequiresReflowOnSizeAvailable = 1u << 0,
+
+ // Used for shapes.
+ RequiresReflowOnFirstFrameCompleteAndLoadEventBlocking = 1u << 1,
+
+ // Internal flag, shouldn't be used by callers.
+ IsBlockingLoadEvent = 1u << 2,
+ };
+
+ explicit ImageLoader(dom::Document* aDocument) : mDocument(aDocument) {
+ MOZ_ASSERT(mDocument);
+ }
+
+ NS_INLINE_DECL_REFCOUNTING(ImageLoader)
+
+ void DropDocumentReference();
+
+ void AssociateRequestToFrame(imgIRequest*, nsIFrame*, Flags = Flags(0));
+ void DisassociateRequestFromFrame(imgIRequest*, nsIFrame*);
+ void DropRequestsForFrame(nsIFrame*);
+
+ void SetAnimationMode(uint16_t aMode);
+
+ // The prescontext for this ImageLoader's document. We need it to be passed
+ // in because this can be called during presentation destruction after the
+ // presshell pointer on the document has been cleared.
+ void ClearFrames(nsPresContext* aPresContext);
+
+ // Triggers an image load.
+ static already_AddRefed<imgRequestProxy> LoadImage(const StyleComputedUrl&,
+ dom::Document&);
+
+ // Usually, only one style value owns a given proxy. However, we have a hack
+ // to share image proxies in chrome documents under some circumstances. We
+ // need to keep track of this so that we don't stop tracking images too early.
+ //
+ // In practice it shouldn't matter as these chrome images are mostly static,
+ // but it is always good to keep sanity.
+ static void NoteSharedLoad(imgRequestProxy*);
+
+ // Undoes what `LoadImage` does.
+ static void UnloadImage(imgRequestProxy*);
+
+ // This is called whenever an image we care about notifies the
+ // GlobalImageObserver.
+ void Notify(imgIRequest*, int32_t aType, const nsIntRect* aData);
+
+ private:
+ // Called when we stop caring about a given request.
+ void DeregisterImageRequest(imgIRequest*, nsPresContext*);
+ struct ImageReflowCallback;
+
+ ~ImageLoader() = default;
+
+ // We need to be able to look up the frames associated with a request (for
+ // delivering notifications) and the requests associated with a frame (when
+ // the frame goes away). Thus we maintain hashtables going both ways. These
+ // should always be in sync.
+
+ struct FrameWithFlags {
+ explicit FrameWithFlags(nsIFrame* aFrame) : mFrame(aFrame) {
+ MOZ_ASSERT(mFrame);
+ }
+ nsIFrame* const mFrame;
+ Flags mFlags{0};
+ };
+
+ // A helper class to compare FrameWithFlags by comparing mFrame and
+ // ignoring mFlags.
+ class FrameOnlyComparator {
+ public:
+ bool Equals(const FrameWithFlags& aElem1,
+ const FrameWithFlags& aElem2) const {
+ return aElem1.mFrame == aElem2.mFrame;
+ }
+
+ bool LessThan(const FrameWithFlags& aElem1,
+ const FrameWithFlags& aElem2) const {
+ return aElem1.mFrame < aElem2.mFrame;
+ }
+ };
+
+ typedef nsTArray<FrameWithFlags> FrameSet;
+ typedef nsTArray<nsCOMPtr<imgIRequest>> RequestSet;
+ typedef nsClassHashtable<nsISupportsHashKey, FrameSet> RequestToFrameMap;
+ typedef nsClassHashtable<nsPtrHashKey<nsIFrame>, RequestSet>
+ FrameToRequestMap;
+
+ nsPresContext* GetPresContext();
+
+ void ImageFrameChanged(imgIRequest*, bool aFirstFrame);
+ void UnblockOnloadIfNeeded(nsIFrame*, imgIRequest*);
+ void UnblockOnloadIfNeeded(FrameWithFlags&);
+
+ void OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage);
+ void OnFrameComplete(imgIRequest* aRequest);
+ void OnImageIsAnimated(imgIRequest* aRequest);
+ void OnFrameUpdate(imgIRequest* aRequest);
+ void OnLoadComplete(imgIRequest* aRequest);
+
+ // Helpers for DropRequestsForFrame / DisassociateRequestFromFrame above.
+ void RemoveRequestToFrameMapping(imgIRequest* aRequest, nsIFrame* aFrame);
+ void RemoveFrameToRequestMapping(imgIRequest* aRequest, nsIFrame* aFrame);
+
+ // A map of imgIRequests to the nsIFrames that are using them.
+ RequestToFrameMap mRequestToFrameMap;
+
+ // A map of nsIFrames to the imgIRequests they use.
+ FrameToRequestMap mFrameToRequestMap;
+
+ // A weak pointer to our document. Nulled out by DropDocumentReference.
+ dom::Document* mDocument;
+};
+
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ImageLoader::Flags)
+
+} // namespace css
+} // namespace mozilla
+
+#endif /* mozilla_css_ImageLoader_h___ */