ImageLoader.h (5515B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 // A class that handles style system image loads (other image loads are handled 8 // by the nodes in the content tree). 9 10 #ifndef mozilla_css_ImageLoader_h___ 11 #define mozilla_css_ImageLoader_h___ 12 13 #include "mozilla/CORSMode.h" 14 #include "nsClassHashtable.h" 15 #include "nsHashKeys.h" 16 #include "nsRect.h" 17 #include "nsTArray.h" 18 19 class nsIFrame; 20 class imgIContainer; 21 class imgIRequest; 22 class imgRequestProxy; 23 class nsPresContext; 24 class nsIURI; 25 class nsIPrincipal; 26 class nsIRequest; 27 28 namespace mozilla { 29 struct MediaFeatureChange; 30 struct StyleComputedUrl; 31 namespace dom { 32 class Document; 33 } 34 35 namespace css { 36 37 /** 38 * NOTE: All methods must be called from the main thread unless otherwise 39 * specified. 40 */ 41 class ImageLoader final { 42 public: 43 static void Init(); 44 static void Shutdown(); 45 46 // We also associate flags alongside frames in the request-to-frames hashmap. 47 // These are used for special handling of events for requests. 48 enum class Flags : uint32_t { 49 // Used for bullets. 50 RequiresReflowOnSizeAvailable = 1u << 0, 51 52 // Used for shapes. 53 RequiresReflowOnFirstFrameCompleteAndLoadEventBlocking = 1u << 1, 54 55 // Internal flag, shouldn't be used by callers. 56 IsBlockingLoadEvent = 1u << 2, 57 }; 58 59 explicit ImageLoader(dom::Document* aDocument) : mDocument(aDocument) { 60 MOZ_ASSERT(mDocument); 61 } 62 63 NS_INLINE_DECL_REFCOUNTING(ImageLoader) 64 65 void DropDocumentReference(); 66 67 void AssociateRequestToFrame(imgIRequest*, nsIFrame*, Flags = Flags(0)); 68 void DisassociateRequestFromFrame(imgIRequest*, nsIFrame*); 69 void DropRequestsForFrame(nsIFrame*); 70 71 void SetAnimationMode(uint16_t aMode); 72 73 // The prescontext for this ImageLoader's document. We need it to be passed 74 // in because this can be called during presentation destruction after the 75 // presshell pointer on the document has been cleared. 76 void ClearFrames(nsPresContext* aPresContext); 77 78 // Triggers an image load. 79 static already_AddRefed<imgRequestProxy> LoadImage(const StyleComputedUrl&, 80 dom::Document&); 81 82 // Usually, only one style value owns a given proxy. However, we have a hack 83 // to share image proxies in chrome documents under some circumstances. We 84 // need to keep track of this so that we don't stop tracking images too early. 85 // 86 // In practice it shouldn't matter as these chrome images are mostly static, 87 // but it is always good to keep sanity. 88 static void NoteSharedLoad(imgRequestProxy*); 89 90 // Undoes what `LoadImage` does. 91 static void UnloadImage(imgRequestProxy*); 92 93 // This is called whenever an image we care about notifies the 94 // GlobalImageObserver. 95 void Notify(imgIRequest*, int32_t aType, const nsIntRect* aData); 96 97 private: 98 // Called when we stop caring about a given request. 99 void DeregisterImageRequest(imgIRequest*, nsPresContext*); 100 struct ImageReflowCallback; 101 102 ~ImageLoader() = default; 103 104 // We need to be able to look up the frames associated with a request (for 105 // delivering notifications) and the requests associated with a frame (when 106 // the frame goes away). Thus we maintain hashtables going both ways. These 107 // should always be in sync. 108 109 struct FrameWithFlags { 110 explicit FrameWithFlags(nsIFrame* aFrame) : mFrame(aFrame) { 111 MOZ_ASSERT(mFrame); 112 } 113 nsIFrame* const mFrame; 114 Flags mFlags{0}; 115 }; 116 117 // A helper class to compare FrameWithFlags by comparing mFrame and 118 // ignoring mFlags. 119 class FrameOnlyComparator { 120 public: 121 bool Equals(const FrameWithFlags& aElem1, 122 const FrameWithFlags& aElem2) const { 123 return aElem1.mFrame == aElem2.mFrame; 124 } 125 126 bool LessThan(const FrameWithFlags& aElem1, 127 const FrameWithFlags& aElem2) const { 128 return aElem1.mFrame < aElem2.mFrame; 129 } 130 }; 131 132 typedef nsTArray<FrameWithFlags> FrameSet; 133 typedef nsTArray<nsCOMPtr<imgIRequest>> RequestSet; 134 typedef nsClassHashtable<nsISupportsHashKey, FrameSet> RequestToFrameMap; 135 typedef nsClassHashtable<nsPtrHashKey<nsIFrame>, RequestSet> 136 FrameToRequestMap; 137 138 nsPresContext* GetPresContext(); 139 140 void ImageFrameChanged(imgIRequest*, bool aFirstFrame); 141 void UnblockOnloadIfNeeded(nsIFrame*, imgIRequest*); 142 void UnblockOnloadIfNeeded(FrameWithFlags&); 143 144 void OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage); 145 void OnFrameComplete(imgIRequest* aRequest); 146 void OnImageIsAnimated(imgIRequest* aRequest); 147 void OnFrameUpdate(imgIRequest* aRequest); 148 void OnLoadComplete(imgIRequest* aRequest); 149 150 // Helpers for DropRequestsForFrame / DisassociateRequestFromFrame above. 151 void RemoveRequestToFrameMapping(imgIRequest* aRequest, nsIFrame* aFrame); 152 void RemoveFrameToRequestMapping(imgIRequest* aRequest, nsIFrame* aFrame); 153 154 // A map of imgIRequests to the nsIFrames that are using them. 155 RequestToFrameMap mRequestToFrameMap; 156 157 // A map of nsIFrames to the imgIRequests they use. 158 FrameToRequestMap mFrameToRequestMap; 159 160 // A weak pointer to our document. Nulled out by DropDocumentReference. 161 dom::Document* mDocument; 162 }; 163 164 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ImageLoader::Flags) 165 166 } // namespace css 167 } // namespace mozilla 168 169 #endif /* mozilla_css_ImageLoader_h___ */