Bug 1869043 assert that graph set access is main thread only r=padenot
[gecko.git] / image / imgRequest.h
blobb948869ae81d2e1eb20286857533972646d7cc9a
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_image_imgRequest_h
8 #define mozilla_image_imgRequest_h
10 #include "nsIChannelEventSink.h"
11 #include "nsIInterfaceRequestor.h"
12 #include "nsIStreamListener.h"
13 #include "nsIThreadRetargetableStreamListener.h"
14 #include "nsIPrincipal.h"
16 #include "nsCOMPtr.h"
17 #include "nsProxyRelease.h"
18 #include "nsString.h"
19 #include "nsError.h"
20 #include "nsIAsyncVerifyRedirectCallback.h"
21 #include "mozilla/Mutex.h"
22 #include "ImageCacheKey.h"
24 class imgCacheValidator;
25 class imgLoader;
26 class imgRequestProxy;
27 class imgCacheEntry;
28 class nsIProperties;
29 class nsIRequest;
30 class nsITimedChannel;
31 class nsIURI;
32 class nsIReferrerInfo;
34 namespace mozilla {
35 enum CORSMode : uint8_t;
36 namespace image {
37 class Image;
38 class ProgressTracker;
39 } // namespace image
40 } // namespace mozilla
42 struct NewPartResult;
44 class imgRequest final : public nsIThreadRetargetableStreamListener,
45 public nsIChannelEventSink,
46 public nsIInterfaceRequestor,
47 public nsIAsyncVerifyRedirectCallback {
48 typedef mozilla::image::Image Image;
49 typedef mozilla::image::ImageCacheKey ImageCacheKey;
50 typedef mozilla::image::ProgressTracker ProgressTracker;
51 typedef mozilla::dom::ReferrerPolicy ReferrerPolicy;
53 public:
54 imgRequest(imgLoader* aLoader, const ImageCacheKey& aCacheKey);
56 NS_DECL_THREADSAFE_ISUPPORTS
57 NS_DECL_NSISTREAMLISTENER
58 NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
59 NS_DECL_NSIREQUESTOBSERVER
60 NS_DECL_NSICHANNELEVENTSINK
61 NS_DECL_NSIINTERFACEREQUESTOR
62 NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
64 [[nodiscard]] nsresult Init(nsIURI* aURI, nsIURI* aFinalURI,
65 bool aHadInsecureRedirect, nsIRequest* aRequest,
66 nsIChannel* aChannel, imgCacheEntry* aCacheEntry,
67 mozilla::dom::Document* aLoadingDocument,
68 nsIPrincipal* aTriggeringPrincipal,
69 mozilla::CORSMode aCORSMode,
70 nsIReferrerInfo* aReferrerInfo);
72 void ClearLoader();
74 // Callers must call imgRequestProxy::Notify later.
75 void AddProxy(imgRequestProxy* proxy);
77 // Whether a given document is allowed to reuse this request without any
78 // revalidation.
79 bool CanReuseWithoutValidation(mozilla::dom::Document*) const;
81 nsresult RemoveProxy(imgRequestProxy* proxy, nsresult aStatus);
83 // Cancel, but also ensure that all work done in Init() is undone. Call this
84 // only when the channel has failed to open, and so calling Cancel() on it
85 // won't be sufficient.
86 void CancelAndAbort(nsresult aStatus);
88 // Called or dispatched by cancel for main thread only execution.
89 void ContinueCancel(nsresult aStatus);
91 // Called or dispatched by EvictFromCache for main thread only execution.
92 void ContinueEvict();
94 // Request that we start decoding the image as soon as data becomes available.
95 void StartDecoding();
97 uint64_t InnerWindowID() const;
98 void SetInnerWindowID(uint64_t aInnerWindowId);
100 // Set the cache validation information (expiry time, whether we must
101 // validate, etc) on the cache entry based on the request information.
102 // If this function is called multiple times, the information set earliest
103 // wins.
104 static void SetCacheValidation(imgCacheEntry* aEntry, nsIRequest* aRequest);
106 bool GetMultipart() const;
108 // Returns whether we went through an insecure (non-HTTPS) redirect at some
109 // point during loading. This does not consider the final URI.
110 bool HadInsecureRedirect() const;
112 // The CORS mode for which we loaded this image.
113 mozilla::CORSMode GetCORSMode() const { return mCORSMode; }
115 // The ReferrerInfo in effect when loading this image.
116 nsIReferrerInfo* GetReferrerInfo() const { return mReferrerInfo; }
118 // The principal for the document that loaded this image. Used when trying to
119 // validate a CORS image load.
120 already_AddRefed<nsIPrincipal> GetTriggeringPrincipal() const;
122 // Return the ProgressTracker associated with this imgRequest. It may live
123 // in |mProgressTracker| or in |mImage.mProgressTracker|, depending on whether
124 // mImage has been instantiated yet.
125 already_AddRefed<ProgressTracker> GetProgressTracker() const;
127 /// Returns the Image associated with this imgRequest, if it's ready.
128 already_AddRefed<Image> GetImage() const;
130 // Get the current principal of the image. No AddRefing.
131 inline nsIPrincipal* GetPrincipal() const { return mPrincipal.get(); }
133 /// Get the ImageCacheKey associated with this request.
134 const ImageCacheKey& CacheKey() const { return mCacheKey; }
136 // Resize the cache entry to 0 if it exists
137 void ResetCacheEntry();
139 // OK to use on any thread.
140 nsresult GetURI(nsIURI** aURI);
141 nsresult GetFinalURI(nsIURI** aURI);
142 bool IsChrome() const;
143 bool IsData() const;
145 nsresult GetImageErrorCode(void);
147 /// Returns a non-owning pointer to this imgRequest's MIME type.
148 const char* GetMimeType() const { return mContentType.get(); }
150 void GetFileName(nsACString& aFileName);
152 /// @return the priority of the underlying network request, or
153 /// PRIORITY_NORMAL if it doesn't support nsISupportsPriority.
154 int32_t Priority() const;
156 /// Adjust the priority of the underlying network request by @aDelta on behalf
157 /// of @aProxy.
158 void AdjustPriority(imgRequestProxy* aProxy, int32_t aDelta);
160 void BoostPriority(uint32_t aCategory);
162 /// Returns a weak pointer to the underlying request.
163 nsIRequest* GetRequest() const { return mRequest; }
165 nsITimedChannel* GetTimedChannel() const { return mTimedChannel; }
167 imgCacheValidator* GetValidator() const { return mValidator; }
168 void SetValidator(imgCacheValidator* aValidator) { mValidator = aValidator; }
170 void* LoadId() const { return mLoadId; }
171 void SetLoadId(void* aLoadId) { mLoadId = aLoadId; }
173 /// Reset the cache entry after we've dropped our reference to it. Used by
174 /// imgLoader when our cache entry is re-requested after we've dropped our
175 /// reference to it.
176 void SetCacheEntry(imgCacheEntry* aEntry);
178 /// Returns whether we've got a reference to the cache entry.
179 bool HasCacheEntry() const;
181 /// Set whether this request is stored in the cache. If it isn't, regardless
182 /// of whether this request has a non-null mCacheEntry, this imgRequest won't
183 /// try to update or modify the image cache.
184 void SetIsInCache(bool aCacheable);
186 void EvictFromCache();
187 void RemoveFromCache();
189 // Sets properties for this image; will dispatch to main thread if needed.
190 void SetProperties(const nsACString& aContentType,
191 const nsACString& aContentDisposition);
193 nsIProperties* Properties() const { return mProperties; }
195 bool HasConsumers() const;
197 bool ImageAvailable() const;
199 bool IsDeniedCrossSiteCORSRequest() const {
200 return mIsDeniedCrossSiteCORSRequest;
203 bool IsCrossSiteNoCORSRequest() const { return mIsCrossSiteNoCORSRequest; }
205 bool ShouldReportRenderTimeForLCP() const {
206 return mShouldReportRenderTimeForLCP;
209 private:
210 friend class FinishPreparingForNewPartRunnable;
212 virtual ~imgRequest();
214 void FinishPreparingForNewPart(const NewPartResult& aResult);
216 void UpdateShouldReportRenderTimeForLCP();
218 void Cancel(nsresult aStatus);
220 // Update the cache entry size based on the image container.
221 void UpdateCacheEntrySize();
223 /// Returns true if StartDecoding() was called.
224 bool IsDecodeRequested() const;
226 void AdjustPriorityInternal(int32_t aDelta);
228 // Weak reference to parent loader; this request cannot outlive its owner.
229 imgLoader* mLoader;
230 nsCOMPtr<nsIRequest> mRequest;
231 // The original URI we were loaded with. This is the same as the URI we are
232 // keyed on in the cache. We store a string here to avoid off main thread
233 // refcounting issues with nsStandardURL.
234 nsCOMPtr<nsIURI> mURI;
235 // The URI of the resource we ended up loading after all redirects, etc.
236 nsCOMPtr<nsIURI> mFinalURI;
237 // The principal which triggered the load of this image. Generally either
238 // the principal of the document the image is being loaded into, or of the
239 // stylesheet which specified the image to load. Used when validating for
240 // CORS.
241 nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
242 // The principal of this image.
243 nsCOMPtr<nsIPrincipal> mPrincipal;
244 nsCOMPtr<nsIProperties> mProperties;
245 nsCOMPtr<nsIChannel> mChannel;
246 nsCOMPtr<nsIInterfaceRequestor> mPrevChannelSink;
248 nsCOMPtr<nsITimedChannel> mTimedChannel;
250 nsCString mContentType;
252 /* we hold on to this to this so long as we have observers */
253 RefPtr<imgCacheEntry> mCacheEntry;
255 /// The key under which this imgRequest is stored in the image cache.
256 ImageCacheKey mCacheKey;
258 void* mLoadId;
260 /// Raw pointer to the first proxy that was added to this imgRequest. Use only
261 /// pointer comparisons; there's no guarantee this will remain valid.
262 void* mFirstProxy;
264 imgCacheValidator* mValidator;
265 nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
266 nsCOMPtr<nsIChannel> mNewRedirectChannel;
268 // The CORS mode (defined in imgIRequest) this image was loaded with. By
269 // default, CORS_NONE.
270 mozilla::CORSMode mCORSMode;
272 // The ReferrerInfo used for this image.
273 nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
275 nsresult mImageErrorCode;
277 // The categories of prioritization strategy that have been requested.
278 uint32_t mBoostCategoriesRequested = 0;
280 // If we've called OnImageAvailable.
281 bool mImageAvailable;
282 bool mIsDeniedCrossSiteCORSRequest;
283 bool mIsCrossSiteNoCORSRequest;
285 bool mShouldReportRenderTimeForLCP;
287 mutable mozilla::Mutex mMutex;
289 // Member variables protected by mMutex. Note that *all* flags in our bitfield
290 // are protected by mMutex; if you're adding a new flag that isn'protected, it
291 // must not be a part of this bitfield.
292 RefPtr<ProgressTracker> mProgressTracker MOZ_GUARDED_BY(mMutex);
293 RefPtr<Image> mImage MOZ_GUARDED_BY(mMutex);
294 bool mIsMultiPartChannel : 1 MOZ_GUARDED_BY(mMutex);
295 bool mIsInCache : 1 MOZ_GUARDED_BY(mMutex);
296 bool mDecodeRequested : 1 MOZ_GUARDED_BY(mMutex);
297 bool mNewPartPending : 1 MOZ_GUARDED_BY(mMutex);
298 bool mHadInsecureRedirect : 1 MOZ_GUARDED_BY(mMutex);
299 // The ID of the inner window origin, used for error reporting.
300 uint64_t mInnerWindowId MOZ_GUARDED_BY(mMutex);
303 #endif // mozilla_image_imgRequest_h