imgRequest.h (10746B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 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/. */ 6 7 #ifndef mozilla_image_imgRequest_h 8 #define mozilla_image_imgRequest_h 9 10 #include "nsIChannelEventSink.h" 11 #include "nsIInterfaceRequestor.h" 12 #include "nsIStreamListener.h" 13 #include "nsIThreadRetargetableStreamListener.h" 14 #include "nsIPrincipal.h" 15 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" 23 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; 33 34 namespace mozilla { 35 enum CORSMode : uint8_t; 36 namespace image { 37 class Image; 38 class ProgressTracker; 39 } // namespace image 40 } // namespace mozilla 41 42 struct NewPartResult; 43 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; 52 53 public: 54 imgRequest(imgLoader* aLoader, const ImageCacheKey& aCacheKey); 55 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 63 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); 71 72 void ClearLoader(); 73 74 // Callers must call imgRequestProxy::Notify later. 75 void AddProxy(imgRequestProxy* proxy); 76 77 // Whether a given document is allowed to reuse this request without any 78 // revalidation. 79 bool CanReuseWithoutValidation(mozilla::dom::Document*) const; 80 81 nsresult RemoveProxy(imgRequestProxy* proxy, nsresult aStatus); 82 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); 87 88 // Called or dispatched by cancel for main thread only execution. 89 void ContinueCancel(nsresult aStatus); 90 91 // Called or dispatched by EvictFromCache for main thread only execution. 92 void ContinueEvict(); 93 94 // Request that we start decoding the image as soon as data becomes available. 95 void StartDecoding(); 96 97 uint64_t InnerWindowID() const; 98 void SetInnerWindowID(uint64_t aInnerWindowId); 99 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 most strict value wins. 103 static void SetCacheValidation(imgCacheEntry* aEntry, nsIRequest* aRequest, 104 bool aForceTouch = false); 105 106 bool GetMultipart() const; 107 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; 111 112 // The CORS mode for which we loaded this image. 113 mozilla::CORSMode GetCORSMode() const { return mCORSMode; } 114 115 // The ReferrerInfo in effect when loading this image. 116 nsIReferrerInfo* GetReferrerInfo() const { return mReferrerInfo; } 117 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; 121 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; 126 127 /// Returns the Image associated with this imgRequest, if it's ready. 128 already_AddRefed<Image> GetImage() const; 129 130 // Get the current principal of the image. No AddRefing. 131 inline nsIPrincipal* GetPrincipal() const { return mPrincipal.get(); } 132 133 /// Get the ImageCacheKey associated with this request. 134 const ImageCacheKey& CacheKey() const { return mCacheKey; } 135 136 // Resize the cache entry to 0 if it exists 137 void ResetCacheEntry(); 138 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; 144 145 nsresult GetImageErrorCode(void); 146 147 /// Returns a non-owning pointer to this imgRequest's MIME type. 148 const char* GetMimeType() const { return mContentType.get(); } 149 150 void GetFileName(nsACString& aFileName); 151 152 /// @return the priority of the underlying network request, or 153 /// PRIORITY_NORMAL if it doesn't support nsISupportsPriority. 154 int32_t Priority() const; 155 156 /// Adjust the priority of the underlying network request by @aDelta on behalf 157 /// of @aProxy. 158 void AdjustPriority(imgRequestProxy* aProxy, int32_t aDelta); 159 160 void BoostPriority(uint32_t aCategory); 161 162 /// Returns a weak pointer to the underlying request. 163 nsIRequest* GetRequest() const { return mRequest; } 164 165 nsITimedChannel* GetTimedChannel() const { return mTimedChannel; } 166 167 imgCacheValidator* GetValidator() const { return mValidator; } 168 void SetValidator(imgCacheValidator* aValidator) { mValidator = aValidator; } 169 170 void* LoadId() const { return mLoadId; } 171 void SetLoadId(void* aLoadId) { mLoadId = aLoadId; } 172 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); 177 178 /// Returns whether we've got a reference to the cache entry. 179 bool HasCacheEntry() const; 180 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); 185 186 void EvictFromCache(); 187 void RemoveFromCache(); 188 189 // Sets properties for this image; will dispatch to main thread if needed. 190 void SetProperties(const nsACString& aContentType, 191 const nsACString& aContentDisposition); 192 193 nsIProperties* Properties() const { return mProperties; } 194 195 bool HasConsumers() const; 196 197 bool ImageAvailable() const; 198 199 bool IsDeniedCrossSiteCORSRequest() const { 200 return mIsDeniedCrossSiteCORSRequest; 201 } 202 203 bool IsCrossSiteNoCORSRequest() const { return mIsCrossSiteNoCORSRequest; } 204 205 bool ShouldReportRenderTimeForLCP() const { 206 return mShouldReportRenderTimeForLCP; 207 } 208 209 private: 210 friend class FinishPreparingForNewPartRunnable; 211 212 virtual ~imgRequest(); 213 214 void FinishPreparingForNewPart(const NewPartResult& aResult); 215 216 void UpdateShouldReportRenderTimeForLCP(); 217 218 void Cancel(nsresult aStatus); 219 220 // Update the cache entry size based on the image container. 221 void UpdateCacheEntrySize(); 222 223 /// Returns true if StartDecoding() was called. 224 bool IsDecodeRequested() const; 225 226 void AdjustPriorityInternal(int32_t aDelta); 227 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; 247 248 nsCOMPtr<nsITimedChannel> mTimedChannel; 249 250 nsCString mContentType; 251 252 /* we hold on to this to this so long as we have observers */ 253 RefPtr<imgCacheEntry> mCacheEntry; 254 255 /// The key under which this imgRequest is stored in the image cache. 256 ImageCacheKey mCacheKey; 257 258 void* mLoadId; 259 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; 263 264 imgCacheValidator* mValidator; 265 nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback; 266 nsCOMPtr<nsIChannel> mNewRedirectChannel; 267 268 // The CORS mode (defined in imgIRequest) this image was loaded with. By 269 // default, CORS_NONE. 270 mozilla::CORSMode mCORSMode; 271 272 // The ReferrerInfo used for this image. 273 nsCOMPtr<nsIReferrerInfo> mReferrerInfo; 274 275 nsresult mImageErrorCode; 276 277 // The categories of prioritization strategy that have been requested. 278 uint32_t mBoostCategoriesRequested = 0; 279 280 // If we've called OnImageAvailable. 281 bool mImageAvailable; 282 bool mIsDeniedCrossSiteCORSRequest; 283 bool mIsCrossSiteNoCORSRequest; 284 285 bool mShouldReportRenderTimeForLCP; 286 // SVGs can't be OffMainThread for example 287 bool mOffMainThreadData = false; 288 289 mutable mozilla::Mutex mMutex; 290 291 // Member variables protected by mMutex. Note that *all* flags in our bitfield 292 // are protected by mMutex; if you're adding a new flag that isn'protected, it 293 // must not be a part of this bitfield. 294 RefPtr<ProgressTracker> mProgressTracker MOZ_GUARDED_BY(mMutex); 295 RefPtr<Image> mImage MOZ_GUARDED_BY(mMutex); 296 bool mIsMultiPartChannel : 1 MOZ_GUARDED_BY(mMutex); 297 bool mIsInCache : 1 MOZ_GUARDED_BY(mMutex); 298 bool mDecodeRequested : 1 MOZ_GUARDED_BY(mMutex); 299 bool mNewPartPending : 1 MOZ_GUARDED_BY(mMutex); 300 bool mHadInsecureRedirect : 1 MOZ_GUARDED_BY(mMutex); 301 // The ID of the inner window origin, used for error reporting. 302 uint64_t mInnerWindowId MOZ_GUARDED_BY(mMutex); 303 }; 304 305 #endif // mozilla_image_imgRequest_h