1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 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___ */
|