tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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